/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 2.0 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 State Query tests.
*//*--------------------------------------------------------------------*/
#include "es2fIntegerStateQueryTests.hpp"
#include "es2fApiCase.hpp"
#include "glsStateQueryUtil.hpp"
#include "gluRenderContext.hpp"
#include "gluContextInfo.hpp"
#include "gluStrUtil.hpp"
#include "tcuRenderTarget.hpp"
#include "deRandom.hpp"
#include "glwEnums.hpp"
using namespace glw; // GLint and other GL types
using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
#ifndef GL_SLUMINANCE_NV
#define GL_SLUMINANCE_NV 0x8C46
#endif
#ifndef GL_SLUMINANCE_ALPHA_NV
#define GL_SLUMINANCE_ALPHA_NV 0x8C44
#endif
#ifndef GL_BGR_NV
#define GL_BGR_NV 0x80E0
#endif
namespace deqp
{
namespace gles2
{
namespace Functional
{
namespace IntegerStateQueryVerifiers
{
// StateVerifier
class StateVerifier : protected glu::CallLogWrapper
{
public:
StateVerifier (const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix);
virtual ~StateVerifier (); // make GCC happy
const char* getTestNamePostfix (void) const;
virtual void verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference) = DE_NULL;
virtual void verifyInteger4 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1, GLint reference2, GLint reference3) = DE_NULL;
virtual void verifyInteger4Mask (tcu::TestContext& testCtx, GLenum name, GLint reference0, bool enableRef0, GLint reference1, bool enableRef1, GLint reference2, bool enableRef2, GLint reference3, bool enableRef3) = DE_NULL;
virtual void verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference) = DE_NULL;
virtual void verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference) = DE_NULL;
virtual void verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1) = DE_NULL;
virtual void verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength) = DE_NULL;
virtual void verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits) = DE_NULL;
private:
const char* const m_testNamePostfix;
};
StateVerifier::StateVerifier (const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix)
: glu::CallLogWrapper (gl, log)
, m_testNamePostfix (testNamePostfix)
{
enableLogging(true);
}
StateVerifier::~StateVerifier ()
{
}
const char* StateVerifier::getTestNamePostfix (void) const
{
return m_testNamePostfix;
}
// GetBooleanVerifier
class GetBooleanVerifier : public StateVerifier
{
public:
GetBooleanVerifier (const glw::Functions& gl, tcu::TestLog& log);
void verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference);
void verifyInteger4 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1, GLint reference2, GLint reference3);
void verifyInteger4Mask (tcu::TestContext& testCtx, GLenum name, GLint reference0, bool enableRef0, GLint reference1, bool enableRef1, GLint reference2, bool enableRef2, GLint reference3, bool enableRef3);
void verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference);
void verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference);
void verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1);
void verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength);
void verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits);
};
GetBooleanVerifier::GetBooleanVerifier (const glw::Functions& gl, tcu::TestLog& log)
: StateVerifier(gl, log, "_getboolean")
{
}
void GetBooleanVerifier::verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLboolean> state;
glGetBooleanv(name, &state);
if (!state.verifyValidity(testCtx))
return;
const GLboolean expectedGLState = reference ? GL_TRUE : GL_FALSE;
if (state != expectedGLState)
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected " << (expectedGLState==GL_TRUE ? "GL_TRUE" : "GL_FALSE") << "; got " << (state == GL_TRUE ? "GL_TRUE" : (state == GL_FALSE ? "GL_FALSE" : "non-boolean")) << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
void GetBooleanVerifier::verifyInteger4 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1, GLint reference2, GLint reference3)
{
verifyInteger4Mask(testCtx, name, reference0, true, reference1, true, reference2, true, reference3, true);
}
void GetBooleanVerifier::verifyInteger4Mask (tcu::TestContext& testCtx, GLenum name, GLint reference0, bool enableRef0, GLint reference1, bool enableRef1, GLint reference2, bool enableRef2, GLint reference3, bool enableRef3)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLboolean[4]> boolVector4;
glGetBooleanv(name, boolVector4);
if (!boolVector4.verifyValidity(testCtx))
return;
const GLboolean referenceAsGLBoolean[] =
{
reference0 ? (GLboolean)GL_TRUE : (GLboolean)GL_FALSE,
reference1 ? (GLboolean)GL_TRUE : (GLboolean)GL_FALSE,
reference2 ? (GLboolean)GL_TRUE : (GLboolean)GL_FALSE,
reference3 ? (GLboolean)GL_TRUE : (GLboolean)GL_FALSE,
};
if ((enableRef0 && (boolVector4[0] != referenceAsGLBoolean[0])) ||
(enableRef1 && (boolVector4[1] != referenceAsGLBoolean[1])) ||
(enableRef2 && (boolVector4[2] != referenceAsGLBoolean[2])) ||
(enableRef3 && (boolVector4[3] != referenceAsGLBoolean[3])))
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected "
<< (enableRef0 ? (referenceAsGLBoolean[0] ? "GL_TRUE" : "GL_FALSE") : " - ") << ", "
<< (enableRef1 ? (referenceAsGLBoolean[1] ? "GL_TRUE" : "GL_FALSE") : " - ") << ", "
<< (enableRef2 ? (referenceAsGLBoolean[2] ? "GL_TRUE" : "GL_FALSE") : " - ") << ", "
<< (enableRef3 ? (referenceAsGLBoolean[3] ? "GL_TRUE" : "GL_FALSE") : " - ") << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
void GetBooleanVerifier::verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLboolean> state;
glGetBooleanv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (state == GL_TRUE) // state is non-zero, could be greater than reference (correct)
return;
if (state == GL_FALSE) // state is zero
{
if (reference > 0) // and reference is greater than zero?
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE" << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
else
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE or GL_FALSE" << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
void GetBooleanVerifier::verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLboolean> state;
glGetBooleanv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (state == GL_TRUE) // state is non-zero, could be greater than reference (correct)
return;
if (state == GL_FALSE) // state is zero
{
if (reference > 0) // and reference is greater than zero?
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE" << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
else
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE or GL_FALSE" << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
void GetBooleanVerifier::verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLboolean[2]> boolVector;
glGetBooleanv(name, boolVector);
if (!boolVector.verifyValidity(testCtx))
return;
const GLboolean referenceAsGLBoolean[2] =
{
reference0 ? (GLboolean)GL_TRUE : (GLboolean)GL_FALSE,
reference1 ? (GLboolean)GL_TRUE : (GLboolean)GL_FALSE
};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(referenceAsGLBoolean); ++ndx)
{
if (boolVector[ndx] == GL_TRUE) // state is non-zero, could be greater than any integer
{
continue;
}
else if (boolVector[ndx] == GL_FALSE) // state is zero
{
if (referenceAsGLBoolean[ndx] > 0) // and reference is greater than zero?
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE" << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
else
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE or GL_FALSE" << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
}
void GetBooleanVerifier::verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLboolean> state;
glGetBooleanv(name, &state);
if (!state.verifyValidity(testCtx))
return;
for (size_t ndx = 0; ndx < referencesLength; ++ndx)
{
const GLboolean expectedGLState = references[ndx] ? GL_TRUE : GL_FALSE;
if (state == expectedGLState)
return;
}
testCtx.getLog() << TestLog::Message << "// ERROR: got " << (state==GL_TRUE ? "GL_TRUE" : "GL_FALSE") << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
void GetBooleanVerifier::verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits)
{
// if stencilBits == 0, the mask is allowed to be either GL_TRUE or GL_FALSE
// otherwise it must be GL_TRUE
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLboolean> state;
glGetBooleanv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (stencilBits > 0 && state != GL_TRUE)
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE" << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
}
}
//GetIntegerVerifier
class GetIntegerVerifier : public StateVerifier
{
public:
GetIntegerVerifier (const glw::Functions& gl, tcu::TestLog& log);
void verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference);
void verifyInteger4 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1, GLint reference2, GLint reference3);
void verifyInteger4Mask (tcu::TestContext& testCtx, GLenum name, GLint reference0, bool enableRef0, GLint reference1, bool enableRef1, GLint reference2, bool enableRef2, GLint reference3, bool enableRef3);
void verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference);
void verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference);
void verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1);
void verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength);
void verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits);
};
GetIntegerVerifier::GetIntegerVerifier (const glw::Functions& gl, tcu::TestLog& log)
: StateVerifier(gl, log, "_getinteger")
{
}
void GetIntegerVerifier::verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint> state;
glGetIntegerv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (state != reference)
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected " << reference << "; got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
}
}
void GetIntegerVerifier::verifyInteger4 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1, GLint reference2, GLint reference3)
{
verifyInteger4Mask(testCtx, name, reference0, true, reference1, true, reference2, true, reference3, true);
}
void GetIntegerVerifier::verifyInteger4Mask (tcu::TestContext& testCtx, GLenum name, GLint reference0, bool enableRef0, GLint reference1, bool enableRef1, GLint reference2, bool enableRef2, GLint reference3, bool enableRef3)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint[4]> intVector4;
glGetIntegerv(name, intVector4);
if (!intVector4.verifyValidity(testCtx))
return;
if ((enableRef0 && (intVector4[0] != reference0)) ||
(enableRef1 && (intVector4[1] != reference1)) ||
(enableRef2 && (intVector4[2] != reference2)) ||
(enableRef3 && (intVector4[3] != reference3)))
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected "
<< (enableRef0?"":"(") << reference0 << (enableRef0?"":")") << ", "
<< (enableRef1?"":"(") << reference1 << (enableRef1?"":")") << ", "
<< (enableRef2?"":"(") << reference2 << (enableRef2?"":")") << ", "
<< (enableRef3?"":"(") << reference3 << (enableRef3?"":")") << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
}
}
void GetIntegerVerifier::verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint> state;
glGetIntegerv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (state < reference)
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << reference << "; got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
}
}
void GetIntegerVerifier::verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint> state;
glGetIntegerv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (GLuint(state) < reference)
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << reference << "; got " << GLuint(state) << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
}
}
void GetIntegerVerifier::verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint[2]> intVector2;
glGetIntegerv(name, intVector2);
if (!intVector2.verifyValidity(testCtx))
return;
if (intVector2[0] < reference0 || intVector2[1] < reference1)
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << reference0 << ", " << reference1 << "; got " << intVector2[0] << ", " << intVector2[0] << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
}
}
void GetIntegerVerifier::verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint> state;
glGetIntegerv(name, &state);
if (!state.verifyValidity(testCtx))
return;
for (size_t ndx = 0; ndx < referencesLength; ++ndx)
{
const GLint expectedGLState = references[ndx];
if (state == expectedGLState)
return;
}
testCtx.getLog() << TestLog::Message << "// ERROR: got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
}
void GetIntegerVerifier::verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint> state;
glGetIntegerv(name, &state);
if (!state.verifyValidity(testCtx))
return;
const GLint reference = (1 << stencilBits) - 1;
if ((state & reference) != reference) // the least significant stencilBits bits should be on
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected minimum mask of " << reference << "; got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid mask value");
}
}
//GetFloatVerifier
class GetFloatVerifier : public StateVerifier
{
public:
GetFloatVerifier (const glw::Functions& gl, tcu::TestLog& log);
void verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference);
void verifyInteger4 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1, GLint reference2, GLint reference3);
void verifyInteger4Mask (tcu::TestContext& testCtx, GLenum name, GLint reference0, bool enableRef0, GLint reference1, bool enableRef1, GLint reference2, bool enableRef2, GLint reference3, bool enableRef3);
void verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference);
void verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference);
void verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1);
void verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength);
void verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits);
};
GetFloatVerifier::GetFloatVerifier (const glw::Functions& gl, tcu::TestLog& log)
: StateVerifier(gl, log, "_getfloat")
{
}
void GetFloatVerifier::verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference)
{
using tcu::TestLog;
const GLfloat referenceAsFloat = GLfloat(reference);
DE_ASSERT(reference == GLint(referenceAsFloat)); // reference integer must have 1:1 mapping to float for this to work. Reference value is always such value in these tests
StateQueryMemoryWriteGuard<GLfloat> state;
glGetFloatv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (state != referenceAsFloat)
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected " << referenceAsFloat << "; got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
}
}
void GetFloatVerifier::verifyInteger4 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1, GLint reference2, GLint reference3)
{
verifyInteger4Mask(testCtx, name, reference0, true, reference1, true, reference2, true, reference3, true);
}
void GetFloatVerifier::verifyInteger4Mask (tcu::TestContext& testCtx, GLenum name, GLint reference0, bool enableRef0, GLint reference1, bool enableRef1, GLint reference2, bool enableRef2, GLint reference3, bool enableRef3)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLfloat[4]> floatVector4;
glGetFloatv(name, floatVector4);
if (!floatVector4.verifyValidity(testCtx))
return;
if ((enableRef0 && (floatVector4[0] != GLfloat(reference0))) ||
(enableRef1 && (floatVector4[1] != GLfloat(reference1))) ||
(enableRef2 && (floatVector4[2] != GLfloat(reference2))) ||
(enableRef3 && (floatVector4[3] != GLfloat(reference3))))
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected "
<< (enableRef0?"":"(") << GLfloat(reference0) << (enableRef0?"":")") << ", "
<< (enableRef1?"":"(") << GLfloat(reference1) << (enableRef1?"":")") << ", "
<< (enableRef2?"":"(") << GLfloat(reference2) << (enableRef2?"":")") << ", "
<< (enableRef3?"":"(") << GLfloat(reference3) << (enableRef3?"":")") << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
}
}
void GetFloatVerifier::verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLfloat> state;
glGetFloatv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (state < GLfloat(reference))
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << GLfloat(reference) << "; got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
}
}
void GetFloatVerifier::verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLfloat> state;
glGetFloatv(name, &state);
if (!state.verifyValidity(testCtx))
return;
if (state < GLfloat(reference))
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << GLfloat(reference) << "; got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
}
}
void GetFloatVerifier::verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLfloat[2]> floatVector2;
glGetFloatv(name, floatVector2);
if (!floatVector2.verifyValidity(testCtx))
return;
if (floatVector2[0] < GLfloat(reference0) || floatVector2[1] < GLfloat(reference1))
{
testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << GLfloat(reference0) << ", " << GLfloat(reference1) << "; got " << floatVector2[0] << ", " << floatVector2[1] << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
}
}
void GetFloatVerifier::verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLfloat> state;
glGetFloatv(name, &state);
if (!state.verifyValidity(testCtx))
return;
for (size_t ndx = 0; ndx < referencesLength; ++ndx)
{
const GLfloat expectedGLState = GLfloat(references[ndx]);
DE_ASSERT(references[ndx] == GLint(expectedGLState)); // reference integer must have 1:1 mapping to float for this to work. Reference value is always such value in these tests
if (state == expectedGLState)
return;
}
testCtx.getLog() << TestLog::Message << "// ERROR: got " << state << TestLog::EndMessage;
if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
}
void GetFloatVerifier::verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits)
{
// checking the mask bits with float doesn't make much sense because of conversion errors
// just verify that the value is greater or equal to the minimum value
const GLint reference = (1 << stencilBits) - 1;
verifyIntegerGreaterOrEqual(testCtx, name, reference);
}
} // IntegerStateQueryVerifiers
namespace
{
using namespace IntegerStateQueryVerifiers;
using namespace deqp::gls::StateQueryUtil;
class ConstantMinimumValueTestCase : public ApiCase
{
public:
ConstantMinimumValueTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum targetName, GLint minValue)
: ApiCase (context, name, description)
, m_targetName (targetName)
, m_minValue (minValue)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyUnsignedIntegerGreaterOrEqual(m_testCtx, m_targetName, m_minValue);
expectError(GL_NO_ERROR);
}
private:
GLenum m_targetName;
GLint m_minValue;
StateVerifier* m_verifier;
};
class SampleBuffersTestCase : public ApiCase
{
public:
SampleBuffersTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
const int expectedSampleBuffers = (m_context.getRenderTarget().getNumSamples() > 1) ? 1 : 0;
m_log << tcu::TestLog::Message << "Sample count is " << (m_context.getRenderTarget().getNumSamples()) << ", expecting GL_SAMPLE_BUFFERS to be " << expectedSampleBuffers << tcu::TestLog::EndMessage;
m_verifier->verifyInteger(m_testCtx, GL_SAMPLE_BUFFERS, expectedSampleBuffers);
expectError(GL_NO_ERROR);
}
private:
StateVerifier* m_verifier;
};
class SamplesTestCase : public ApiCase
{
public:
SamplesTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
// MSAA?
if (m_context.getRenderTarget().getNumSamples() > 1)
{
m_log << tcu::TestLog::Message << "Sample count is " << (m_context.getRenderTarget().getNumSamples()) << tcu::TestLog::EndMessage;
m_verifier->verifyInteger(m_testCtx, GL_SAMPLES, m_context.getRenderTarget().getNumSamples());
expectError(GL_NO_ERROR);
}
else
{
const glw::GLint validSamples[] = {0, 1};
m_log << tcu::TestLog::Message << "Expecting GL_SAMPLES to be 0 or 1" << tcu::TestLog::EndMessage;
m_verifier->verifyIntegerAnyOf(m_testCtx, GL_SAMPLES, validSamples, DE_LENGTH_OF_ARRAY(validSamples));
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class HintTestCase : public ApiCase
{
public:
HintTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum targetName)
: ApiCase (context, name, description)
, m_targetName (targetName)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_targetName, GL_DONT_CARE);
expectError(GL_NO_ERROR);
glHint(m_targetName, GL_NICEST);
m_verifier->verifyInteger(m_testCtx, m_targetName, GL_NICEST);
expectError(GL_NO_ERROR);
glHint(m_targetName, GL_FASTEST);
m_verifier->verifyInteger(m_testCtx, m_targetName, GL_FASTEST);
expectError(GL_NO_ERROR);
glHint(m_targetName, GL_DONT_CARE);
m_verifier->verifyInteger(m_testCtx, m_targetName, GL_DONT_CARE);
expectError(GL_NO_ERROR);
}
private:
GLenum m_targetName;
StateVerifier* m_verifier;
};
class DepthFuncTestCase : public ApiCase
{
public:
DepthFuncTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, GL_DEPTH_FUNC, GL_LESS);
expectError(GL_NO_ERROR);
const GLenum depthFunctions[] = {GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GREATER, GL_GEQUAL, GL_NOTEQUAL};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthFunctions); ndx++)
{
glDepthFunc(depthFunctions[ndx]);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, GL_DEPTH_FUNC, depthFunctions[ndx]);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class CullFaceTestCase : public ApiCase
{
public:
CullFaceTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, GL_CULL_FACE_MODE, GL_BACK);
expectError(GL_NO_ERROR);
const GLenum cullFaces[] = {GL_FRONT, GL_BACK, GL_FRONT_AND_BACK};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cullFaces); ndx++)
{
glCullFace(cullFaces[ndx]);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, GL_CULL_FACE_MODE, cullFaces[ndx]);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class FrontFaceTestCase : public ApiCase
{
public:
FrontFaceTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, GL_FRONT_FACE, GL_CCW);
expectError(GL_NO_ERROR);
const GLenum frontFaces[] = {GL_CW, GL_CCW};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(frontFaces); ndx++)
{
glFrontFace(frontFaces[ndx]);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, GL_FRONT_FACE, frontFaces[ndx]);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class ViewPortTestCase : public ApiCase
{
public:
ViewPortTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
de::Random rnd(0xabcdef);
GLint maxViewportDimensions[2] = {0};
GLfloat viewportBoundsRange[2] = {0.0f};
GLboolean hasViewportArray = false;
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDimensions);
hasViewportArray = m_context.getContextInfo().isExtensionSupported("GL_OES_viewport_array") ||
m_context.getContextInfo().isExtensionSupported("GL_NV_viewport_array");
if (hasViewportArray)
{
glGetFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewportBoundsRange);
}
// verify initial value of first two values
m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, 0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
expectError(GL_NO_ERROR);
const int numIterations = 120;
for (int i = 0; i < numIterations; ++i)
{
GLint x = rnd.getInt(-64000, 64000);
GLint y = rnd.getInt(-64000, 64000);
GLsizei width = rnd.getInt(0, maxViewportDimensions[0]);
GLsizei height = rnd.getInt(0, maxViewportDimensions[1]);
glViewport(x, y, width, height);
if (hasViewportArray)
{
m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT,
de::clamp(x, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
de::clamp(y, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
width, height);
}
else
{
m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
}
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class ScissorBoxTestCase : public ApiCase
{
public:
ScissorBoxTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
de::Random rnd(0xabcdef);
// verify initial value
m_verifier->verifyInteger4(m_testCtx, GL_SCISSOR_BOX, 0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
expectError(GL_NO_ERROR);
const int numIterations = 120;
for (int i = 0; i < numIterations; ++i)
{
GLint left = rnd.getInt(-64000, 64000);
GLint bottom = rnd.getInt(-64000, 64000);
GLsizei width = rnd.getInt(0, 64000);
GLsizei height = rnd.getInt(0, 64000);
glScissor(left, bottom, width, height);
m_verifier->verifyInteger4(m_testCtx, GL_SCISSOR_BOX, left, bottom, width, height);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class MaxViewportDimsTestCase : public ApiCase
{
public:
MaxViewportDimsTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyIntegerGreaterOrEqual2(m_testCtx, GL_MAX_VIEWPORT_DIMS, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
expectError(GL_NO_ERROR);
}
private:
StateVerifier* m_verifier;
};
class StencilRefTestCase : public ApiCase
{
public:
StencilRefTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_testTargetName, 0);
expectError(GL_NO_ERROR);
const int stencilBits = m_context.getRenderTarget().getStencilBits();
for (int stencilBit = 0; stencilBit < stencilBits; ++stencilBit)
{
const int ref = 1 << stencilBit;
glStencilFunc(GL_ALWAYS, ref, 0); // mask should not affect the REF
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, ref);
expectError(GL_NO_ERROR);
glStencilFunc(GL_ALWAYS, ref, ref);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, ref);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
};
class StencilRefSeparateTestCase : public ApiCase
{
public:
StencilRefSeparateTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, GLenum stencilFuncTargetFace)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
, m_stencilFuncTargetFace (stencilFuncTargetFace)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_testTargetName, 0);
expectError(GL_NO_ERROR);
const int stencilBits = m_context.getRenderTarget().getStencilBits();
for (int stencilBit = 0; stencilBit < stencilBits; ++stencilBit)
{
const int ref = 1 << stencilBit;
glStencilFuncSeparate(m_stencilFuncTargetFace, GL_ALWAYS, ref, 0);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, ref);
expectError(GL_NO_ERROR);
glStencilFuncSeparate(m_stencilFuncTargetFace, GL_ALWAYS, ref, ref);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, ref);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
GLenum m_stencilFuncTargetFace;
};
class StencilOpTestCase : public ApiCase
{
public:
StencilOpTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum stencilOpName)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_stencilOpName (stencilOpName)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_stencilOpName, GL_KEEP);
expectError(GL_NO_ERROR);
const GLenum stencilOpValues[] = {GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilOpValues); ++ndx)
{
SetStencilOp(stencilOpValues[ndx]);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_stencilOpName, stencilOpValues[ndx]);
expectError(GL_NO_ERROR);
}
}
protected:
virtual void SetStencilOp (GLenum stencilOpValue)
{
switch (m_stencilOpName)
{
case GL_STENCIL_FAIL:
case GL_STENCIL_BACK_FAIL:
glStencilOp(stencilOpValue, GL_KEEP, GL_KEEP);
break;
case GL_STENCIL_PASS_DEPTH_FAIL:
case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
glStencilOp(GL_KEEP, stencilOpValue, GL_KEEP);
break;
case GL_STENCIL_PASS_DEPTH_PASS:
case GL_STENCIL_BACK_PASS_DEPTH_PASS:
glStencilOp(GL_KEEP, GL_KEEP, stencilOpValue);
break;
default:
DE_ASSERT(false && "should not happen");
break;
}
}
StateVerifier* m_verifier;
GLenum m_stencilOpName;
};
class StencilOpSeparateTestCase : public StencilOpTestCase
{
public:
StencilOpSeparateTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum stencilOpName, GLenum stencilOpFace)
: StencilOpTestCase (context, verifier, name, description, stencilOpName)
, m_stencilOpFace (stencilOpFace)
{
}
private:
void SetStencilOp (GLenum stencilOpValue)
{
switch (m_stencilOpName)
{
case GL_STENCIL_FAIL:
case GL_STENCIL_BACK_FAIL:
glStencilOpSeparate(m_stencilOpFace, stencilOpValue, GL_KEEP, GL_KEEP);
break;
case GL_STENCIL_PASS_DEPTH_FAIL:
case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
glStencilOpSeparate(m_stencilOpFace, GL_KEEP, stencilOpValue, GL_KEEP);
break;
case GL_STENCIL_PASS_DEPTH_PASS:
case GL_STENCIL_BACK_PASS_DEPTH_PASS:
glStencilOpSeparate(m_stencilOpFace, GL_KEEP, GL_KEEP, stencilOpValue);
break;
default:
DE_ASSERT(false && "should not happen");
break;
}
}
GLenum m_stencilOpFace;
};
class StencilFuncTestCase : public ApiCase
{
public:
StencilFuncTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, GL_STENCIL_FUNC, GL_ALWAYS);
expectError(GL_NO_ERROR);
const GLenum stencilfuncValues[] = {GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilfuncValues); ++ndx)
{
glStencilFunc(stencilfuncValues[ndx], 0, 0);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, GL_STENCIL_FUNC, stencilfuncValues[ndx]);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, GL_STENCIL_BACK_FUNC, stencilfuncValues[ndx]);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class StencilFuncSeparateTestCase : public ApiCase
{
public:
StencilFuncSeparateTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum stencilFuncName, GLenum stencilFuncFace)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_stencilFuncName (stencilFuncName)
, m_stencilFuncFace (stencilFuncFace)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_stencilFuncName, GL_ALWAYS);
expectError(GL_NO_ERROR);
const GLenum stencilfuncValues[] = {GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(stencilfuncValues); ++ndx)
{
glStencilFuncSeparate(m_stencilFuncFace, stencilfuncValues[ndx], 0, 0);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_stencilFuncName, stencilfuncValues[ndx]);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_stencilFuncName;
GLenum m_stencilFuncFace;
};
class StencilMaskTestCase : public ApiCase
{
public:
StencilMaskTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
{
}
void test (void)
{
const int stencilBits = m_context.getRenderTarget().getStencilBits();
m_verifier->verifyStencilMaskInitial(m_testCtx, m_testTargetName, stencilBits);
expectError(GL_NO_ERROR);
for (int stencilBit = 0; stencilBit < stencilBits; ++stencilBit)
{
const int mask = 1 << stencilBit;
glStencilFunc(GL_ALWAYS, 0, mask);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, mask);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
};
class StencilMaskSeparateTestCase : public ApiCase
{
public:
StencilMaskSeparateTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, GLenum stencilFuncTargetFace)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
, m_stencilFuncTargetFace (stencilFuncTargetFace)
{
}
void test (void)
{
const int stencilBits = m_context.getRenderTarget().getStencilBits();
m_verifier->verifyStencilMaskInitial(m_testCtx, m_testTargetName, stencilBits);
expectError(GL_NO_ERROR);
for (int stencilBit = 0; stencilBit < stencilBits; ++stencilBit)
{
const int mask = 1 << stencilBit;
glStencilFuncSeparate(m_stencilFuncTargetFace, GL_ALWAYS, 0, mask);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, mask);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
GLenum m_stencilFuncTargetFace;
};
class StencilWriteMaskTestCase : public ApiCase
{
public:
StencilWriteMaskTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
{
}
void test (void)
{
const int stencilBits = m_context.getRenderTarget().getStencilBits();
for (int stencilBit = 0; stencilBit < stencilBits; ++stencilBit)
{
const int mask = 1 << stencilBit;
glStencilMask(mask);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, mask);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
};
class StencilWriteMaskSeparateTestCase : public ApiCase
{
public:
StencilWriteMaskSeparateTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, GLenum stencilTargetFace)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
, m_stencilTargetFace (stencilTargetFace)
{
}
void test (void)
{
const int stencilBits = m_context.getRenderTarget().getStencilBits();
for (int stencilBit = 0; stencilBit < stencilBits; ++stencilBit)
{
const int mask = 1 << stencilBit;
glStencilMaskSeparate(m_stencilTargetFace, mask);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, mask);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
GLenum m_stencilTargetFace;
};
class PixelStoreAlignTestCase : public ApiCase
{
public:
PixelStoreAlignTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_testTargetName, 4);
expectError(GL_NO_ERROR);
const int alignments[] = {1, 2, 4, 8};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(alignments); ++ndx)
{
const int referenceValue = alignments[ndx];
glPixelStorei(m_testTargetName, referenceValue);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, referenceValue);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
};
class BlendFuncTestCase : public ApiCase
{
public:
BlendFuncTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, int initialValue)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
, m_initialValue (initialValue)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_testTargetName, m_initialValue);
expectError(GL_NO_ERROR);
const GLenum blendFuncValues[] =
{
GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR,
GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA,
GL_SRC_ALPHA_SATURATE
};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(blendFuncValues); ++ndx)
{
const GLenum referenceValue = blendFuncValues[ndx];
//GL_SRC_ALPHA_SATURATE is ony allowed for srcRGB or srcA
if (referenceValue == GL_SRC_ALPHA_SATURATE &&
!(m_testTargetName == GL_BLEND_SRC_RGB || m_testTargetName == GL_BLEND_SRC_ALPHA))
continue;
SetBlendFunc(referenceValue);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, referenceValue);
expectError(GL_NO_ERROR);
}
}
protected:
virtual void SetBlendFunc (GLenum func)
{
switch (m_testTargetName)
{
case GL_BLEND_SRC_RGB:
case GL_BLEND_SRC_ALPHA:
glBlendFunc(func, GL_ZERO);
break;
case GL_BLEND_DST_RGB:
case GL_BLEND_DST_ALPHA:
glBlendFunc(GL_ZERO, func);
break;
default:
DE_ASSERT(false && "should not happen");
break;
}
}
StateVerifier* m_verifier;
GLenum m_testTargetName;
int m_initialValue;
};
class BlendFuncSeparateTestCase : public BlendFuncTestCase
{
public:
BlendFuncSeparateTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, int initialValue)
: BlendFuncTestCase (context, verifier, name, description, testTargetName, initialValue)
{
}
void SetBlendFunc (GLenum func)
{
switch (m_testTargetName)
{
case GL_BLEND_SRC_RGB:
glBlendFuncSeparate(func, GL_ZERO, GL_ZERO, GL_ZERO);
break;
case GL_BLEND_DST_RGB:
glBlendFuncSeparate(GL_ZERO, func, GL_ZERO, GL_ZERO);
break;
case GL_BLEND_SRC_ALPHA:
glBlendFuncSeparate(GL_ZERO, GL_ZERO, func, GL_ZERO);
break;
case GL_BLEND_DST_ALPHA:
glBlendFuncSeparate(GL_ZERO, GL_ZERO, GL_ZERO, func);
break;
default:
DE_ASSERT(false && "should not happen");
break;
}
}
};
class BlendEquationTestCase : public ApiCase
{
public:
BlendEquationTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, int initialValue)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
, m_initialValue (initialValue)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, m_testTargetName, m_initialValue);
expectError(GL_NO_ERROR);
const GLenum blendFuncValues[] =
{
GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT
};
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(blendFuncValues); ++ndx)
{
const GLenum referenceValue = blendFuncValues[ndx];
SetBlendEquation(referenceValue);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, m_testTargetName, referenceValue);
expectError(GL_NO_ERROR);
}
}
protected:
virtual void SetBlendEquation (GLenum equation)
{
glBlendEquation(equation);
}
StateVerifier* m_verifier;
GLenum m_testTargetName;
int m_initialValue;
};
class BlendEquationSeparateTestCase : public BlendEquationTestCase
{
public:
BlendEquationSeparateTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, int initialValue)
: BlendEquationTestCase (context, verifier, name, description, testTargetName, initialValue)
{
}
protected:
void SetBlendEquation (GLenum equation)
{
switch (m_testTargetName)
{
case GL_BLEND_EQUATION_RGB:
glBlendEquationSeparate(equation, GL_FUNC_ADD);
break;
case GL_BLEND_EQUATION_ALPHA:
glBlendEquationSeparate(GL_FUNC_ADD, equation);
break;
default:
DE_ASSERT(false && "should not happen");
break;
}
}
};
class ImplementationArrayTestCase : public ApiCase
{
public:
ImplementationArrayTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum testTargetName, GLenum testTargetLengthTargetName, int minValue)
: ApiCase (context, name, description)
, m_verifier (verifier)
, m_testTargetName (testTargetName)
, m_testTargetLengthTargetName (testTargetLengthTargetName)
, m_minValue (minValue)
{
}
void test (void)
{
m_verifier->verifyIntegerGreaterOrEqual(m_testCtx, m_testTargetLengthTargetName, m_minValue);
expectError(GL_NO_ERROR);
GLint targetArrayLength = 0;
glGetIntegerv(m_testTargetLengthTargetName, &targetArrayLength);
expectError(GL_NO_ERROR);
if (targetArrayLength)
{
std::vector<GLint> queryResult;
queryResult.resize(targetArrayLength, 0);
glGetIntegerv(m_testTargetName, &queryResult[0]);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
GLenum m_testTargetName;
GLenum m_testTargetLengthTargetName;
int m_minValue;
};
class BindingTest : public TestCase
{
public:
BindingTest (Context& context,
const char* name,
const char* desc,
QueryType type);
IterateResult iterate (void);
virtual void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const = 0;
protected:
const QueryType m_type;
};
BindingTest::BindingTest (Context& context,
const char* name,
const char* desc,
QueryType type)
: TestCase (context, name, desc)
, m_type (type)
{
}
BindingTest::IterateResult BindingTest::iterate (void)
{
glu::CallLogWrapper gl (m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
tcu::ResultCollector result (m_context.getTestContext().getLog(), " // ERROR: ");
gl.enableLogging(true);
test(gl, result);
result.setTestContextResult(m_testCtx);
return STOP;
}
class CurrentProgramBindingTestCase : public BindingTest
{
public:
CurrentProgramBindingTestCase (Context& context, QueryType type, const char* name, const char* description)
: BindingTest(context, name, description, type)
{
}
void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const
{
static const char* testVertSource =
"void main (void)\n"
"{\n"
" gl_Position = vec4(0.0);\n"
"}\n";
static const char* testFragSource =
"void main (void)\n"
"{\n"
" gl_FragColor = vec4(0.0);\n"
"}\n";
GLuint shaderVert;
GLuint shaderFrag;
GLuint shaderProg;
GLint compileStatus;
GLint linkStatus;
{
const tcu::ScopedLogSection section(gl.getLog(), "Initial", "Initial");
verifyStateInteger(result, gl, GL_CURRENT_PROGRAM, 0, m_type);
}
{
const tcu::ScopedLogSection section(gl.getLog(), "VertexShader", "Vertex Shader");
shaderVert = gl.glCreateShader(GL_VERTEX_SHADER);
gl.glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
gl.glCompileShader(shaderVert);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glCompileShader");
gl.glGetShaderiv(shaderVert, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus != GL_TRUE)
result.fail("expected GL_TRUE");
}
{
const tcu::ScopedLogSection section(gl.getLog(), "FragmentShader", "Fragment Shader");
shaderFrag = gl.glCreateShader(GL_FRAGMENT_SHADER);
gl.glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
gl.glCompileShader(shaderFrag);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glCompileShader");
gl.glGetShaderiv(shaderFrag, GL_COMPILE_STATUS, &compileStatus);
if (compileStatus != GL_TRUE)
result.fail("expected GL_TRUE");
}
{
const tcu::ScopedLogSection section(gl.getLog(), "Program", "Create and bind program");
shaderProg = gl.glCreateProgram();
gl.glAttachShader(shaderProg, shaderVert);
gl.glAttachShader(shaderProg, shaderFrag);
gl.glLinkProgram(shaderProg);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glLinkProgram");
gl.glGetProgramiv(shaderProg, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE)
result.fail("expected GL_TRUE");
gl.glUseProgram(shaderProg);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glUseProgram");
verifyStateInteger(result, gl, GL_CURRENT_PROGRAM, shaderProg, m_type);
}
{
const tcu::ScopedLogSection section(gl.getLog(), "Delete", "Delete program while in use");
gl.glDeleteShader(shaderVert);
gl.glDeleteShader(shaderFrag);
gl.glDeleteProgram(shaderProg);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteProgram");
verifyStateInteger(result, gl, GL_CURRENT_PROGRAM, shaderProg, m_type);
}
{
const tcu::ScopedLogSection section(gl.getLog(), "Unbind", "Unbind program");
gl.glUseProgram(0);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glUseProgram");
verifyStateInteger(result, gl, GL_CURRENT_PROGRAM, 0, m_type);
}
}
};
class BufferBindingTestCase : public BindingTest
{
public:
BufferBindingTestCase (Context& context, QueryType type, const char* name, const char* description, GLenum bufferBindingName, GLenum bufferType)
: BindingTest (context, name, description, type)
, m_bufferBindingName (bufferBindingName)
, m_bufferType (bufferType)
{
}
void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const
{
verifyStateInteger(result, gl, m_bufferBindingName, 0, m_type);
GLuint bufferObject = 0;
gl.glGenBuffers(1, &bufferObject);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenBuffers");
gl.glBindBuffer(m_bufferType, bufferObject);
verifyStateInteger(result, gl, m_bufferBindingName, bufferObject, m_type);
gl.glDeleteBuffers(1, &bufferObject);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteBuffers");
verifyStateInteger(result, gl, m_bufferBindingName, 0, m_type);
}
private:
const GLenum m_bufferBindingName;
const GLenum m_bufferType;
};
class StencilClearValueTestCase : public ApiCase
{
public:
StencilClearValueTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, GL_STENCIL_CLEAR_VALUE, 0);
expectError(GL_NO_ERROR);
const int stencilBits = m_context.getRenderTarget().getStencilBits();
for (int stencilBit = 0; stencilBit < stencilBits; ++stencilBit)
{
const int ref = 1 << stencilBit;
glClearStencil(ref);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, GL_STENCIL_CLEAR_VALUE, ref);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class ActiveTextureTestCase : public ApiCase
{
public:
ActiveTextureTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyInteger(m_testCtx, GL_ACTIVE_TEXTURE, GL_TEXTURE0);
expectError(GL_NO_ERROR);
GLint textureUnits = 0;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &textureUnits);
expectError(GL_NO_ERROR);
for (int ndx = 0; ndx < textureUnits; ++ndx)
{
glActiveTexture(GL_TEXTURE0 + ndx);
expectError(GL_NO_ERROR);
m_verifier->verifyInteger(m_testCtx, GL_ACTIVE_TEXTURE, GL_TEXTURE0 + ndx);
expectError(GL_NO_ERROR);
}
}
private:
StateVerifier* m_verifier;
};
class RenderbufferBindingTestCase : public BindingTest
{
public:
RenderbufferBindingTestCase (Context& context, QueryType type, const char* name, const char* description)
: BindingTest(context, name, description, type)
{
}
void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const
{
verifyStateInteger(result, gl, GL_RENDERBUFFER_BINDING, 0, m_type);
GLuint renderBuffer = 0;
gl.glGenRenderbuffers(1, &renderBuffer);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenRenderbuffers");
gl.glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glBindRenderbuffer");
verifyStateInteger(result, gl, GL_RENDERBUFFER_BINDING, renderBuffer, m_type);
gl.glDeleteRenderbuffers(1, &renderBuffer);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteRenderbuffers");
verifyStateInteger(result, gl, GL_RENDERBUFFER_BINDING, 0, m_type);
}
};
class TextureBindingTestCase : public BindingTest
{
public:
TextureBindingTestCase (Context& context, QueryType type, const char* name, const char* description, GLenum testBindingName, GLenum textureType)
: BindingTest (context, name, description, type)
, m_testBindingName (testBindingName)
, m_textureType (textureType)
{
}
void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const
{
verifyStateInteger(result, gl, m_testBindingName, 0, m_type);
GLuint texture = 0;
gl.glGenTextures(1, &texture);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenTextures");
gl.glBindTexture(m_textureType, texture);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glBindTexture");
verifyStateInteger(result, gl, m_testBindingName, texture, m_type);
gl.glDeleteTextures(1, &texture);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteTextures");
verifyStateInteger(result, gl, m_testBindingName, 0, m_type);
}
private:
const GLenum m_testBindingName;
const GLenum m_textureType;
};
class FrameBufferBindingTestCase : public BindingTest
{
public:
FrameBufferBindingTestCase (Context& context, QueryType type, const char* name, const char* description)
: BindingTest(context, name, description, type)
{
}
void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const
{
verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, 0, m_type);
GLuint framebufferId = 0;
gl.glGenFramebuffers(1, &framebufferId);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenFramebuffers");
gl.glBindFramebuffer(GL_FRAMEBUFFER, framebufferId);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glBindFramebuffer");
verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, framebufferId, m_type);
gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glBindFramebuffer");
verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, 0, m_type);
gl.glBindFramebuffer(GL_FRAMEBUFFER, framebufferId);
gl.glDeleteFramebuffers(1, &framebufferId);
GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteFramebuffers");
verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, 0, m_type);
}
};
class ImplementationColorReadTestCase : public ApiCase
{
public:
ImplementationColorReadTestCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
const GLint defaultColorTypes[] =
{
GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_5_6_5
};
const GLint defaultColorFormats[] =
{
GL_RGBA, GL_RGB, GL_ALPHA
};
std::vector<GLint> validColorTypes;
std::vector<GLint> validColorFormats;
// Defined by the spec
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(defaultColorTypes); ++ndx)
validColorTypes.push_back(defaultColorTypes[ndx]);
for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(defaultColorFormats); ++ndx)
validColorFormats.push_back(defaultColorFormats[ndx]);
// Extensions
if (m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888") ||
m_context.getContextInfo().isExtensionSupported("GL_APPLE_texture_format_BGRA8888"))
validColorFormats.push_back(GL_BGRA);
if (m_context.getContextInfo().isExtensionSupported("GL_EXT_read_format_bgra"))
{
validColorFormats.push_back(GL_BGRA);
validColorTypes.push_back(GL_UNSIGNED_SHORT_4_4_4_4_REV);
validColorTypes.push_back(GL_UNSIGNED_SHORT_1_5_5_5_REV);
}
if (m_context.getContextInfo().isExtensionSupported("GL_IMG_read_format"))
{
validColorFormats.push_back(GL_BGRA);
validColorTypes.push_back(GL_UNSIGNED_SHORT_4_4_4_4_REV);
}
if (m_context.getContextInfo().isExtensionSupported("GL_NV_sRGB_formats"))
{
validColorFormats.push_back(GL_SLUMINANCE_NV);
validColorFormats.push_back(GL_SLUMINANCE_ALPHA_NV);
}
if (m_context.getContextInfo().isExtensionSupported("GL_NV_bgr"))
{
validColorFormats.push_back(GL_BGR_NV);
}
if (m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_rg"))
{
validColorFormats.push_back(GL_RED);
validColorFormats.push_back(GL_RG);
}
m_verifier->verifyIntegerAnyOf(m_testCtx, GL_IMPLEMENTATION_COLOR_READ_TYPE, &validColorTypes[0], validColorTypes.size());
m_verifier->verifyIntegerAnyOf(m_testCtx, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &validColorFormats[0], validColorFormats.size());
expectError(GL_NO_ERROR);
}
private:
StateVerifier* m_verifier;
};
class BufferComponentSizeCase : public ApiCase
{
public:
BufferComponentSizeCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
: ApiCase (context, name, description)
, m_verifier (verifier)
{
}
void test (void)
{
m_verifier->verifyIntegerGreaterOrEqual(m_testCtx, GL_RED_BITS, m_context.getRenderTarget().getPixelFormat().redBits);
m_verifier->verifyIntegerGreaterOrEqual(m_testCtx, GL_BLUE_BITS, m_context.getRenderTarget().getPixelFormat().blueBits);
m_verifier->verifyIntegerGreaterOrEqual(m_testCtx, GL_GREEN_BITS, m_context.getRenderTarget().getPixelFormat().greenBits);
m_verifier->verifyIntegerGreaterOrEqual(m_testCtx, GL_ALPHA_BITS, m_context.getRenderTarget().getPixelFormat().alphaBits);
expectError(GL_NO_ERROR);
m_verifier->verifyIntegerGreaterOrEqual(m_testCtx, GL_DEPTH_BITS, m_context.getRenderTarget().getDepthBits());
m_verifier->verifyIntegerGreaterOrEqual(m_testCtx, GL_STENCIL_BITS, m_context.getRenderTarget().getStencilBits());
expectError(GL_NO_ERROR);
}
private:
StateVerifier* m_verifier;
};
static const char* getQueryTypeSuffix (QueryType type)
{
switch (type)
{
case QUERY_BOOLEAN: return "_getboolean";
case QUERY_INTEGER: return "_getinteger";
case QUERY_FLOAT: return "_getfloat";
default:
DE_ASSERT(DE_FALSE);
return DE_NULL;
}
}
#define FOR_EACH_VERIFIER(VERIFIERS, CODE_BLOCK) \
for (int _verifierNdx = 0; _verifierNdx < DE_LENGTH_OF_ARRAY(VERIFIERS); _verifierNdx++) \
{ \
StateVerifier* verifier = (VERIFIERS)[_verifierNdx]; \
CODE_BLOCK; \
}
#define FOR_EACH_QUERYTYPE(QUERYTYPES, CODE_BLOCK) \
for (int _queryTypeNdx = 0; _queryTypeNdx < DE_LENGTH_OF_ARRAY(QUERYTYPES); _queryTypeNdx++) \
{ \
const QueryType queryType = (QUERYTYPES)[_queryTypeNdx]; \
CODE_BLOCK; \
}
} // anonymous
IntegerStateQueryTests::IntegerStateQueryTests (Context& context)
: TestCaseGroup (context, "integers", "Integer Values")
, m_verifierBoolean (DE_NULL)
, m_verifierInteger (DE_NULL)
, m_verifierFloat (DE_NULL)
{
}
IntegerStateQueryTests::~IntegerStateQueryTests (void)
{
deinit();
}
void IntegerStateQueryTests::init (void)
{
static const QueryType queryTypes[] =
{
QUERY_BOOLEAN,
QUERY_INTEGER,
QUERY_FLOAT,
};
DE_ASSERT(m_verifierBoolean == DE_NULL);
DE_ASSERT(m_verifierInteger == DE_NULL);
DE_ASSERT(m_verifierFloat == DE_NULL);
m_verifierBoolean = new GetBooleanVerifier (m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
m_verifierInteger = new GetIntegerVerifier (m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
m_verifierFloat = new GetFloatVerifier (m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
const struct LimitedStateInteger
{
const char* name;
const char* description;
GLenum targetName;
GLint value;
} implementationMinLimits[] =
{
{ "subpixel_bits", "SUBPIXEL_BITS has a minimum value of 4", GL_SUBPIXEL_BITS, 4 },
{ "max_texture_size", "MAX_TEXTURE_SIZE has a minimum value of 64", GL_MAX_TEXTURE_SIZE, 64 },
{ "max_cube_map_texture_size", "MAX_CUBE_MAP_TEXTURE_SIZE has a minimum value of 16", GL_MAX_CUBE_MAP_TEXTURE_SIZE, 16 },
{ "max_vertex_attribs", "MAX_VERTEX_ATTRIBS has a minimum value of 8", GL_MAX_VERTEX_ATTRIBS, 8 },
{ "max_vertex_uniform_vectors", "MAX_VERTEX_UNIFORM_VECTORS has a minimum value of 128", GL_MAX_VERTEX_UNIFORM_VECTORS, 128 },
{ "max_varying_vectors", "MAX_VARYING_VECTORS has a minimum value of 8", GL_MAX_VARYING_VECTORS, 8 },
{ "max_combined_texture_image_units", "MAX_COMBINED_TEXTURE_IMAGE_UNITS has a minimum value of 8", GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, 8 },
{ "max_vertex_texture_image_units", "MAX_VERTEX_TEXTURE_IMAGE_UNITS has a minimum value of 0", GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, 0 },
{ "max_texture_image_units", "MAX_TEXTURE_IMAGE_UNITS has a minimum value of 8", GL_MAX_TEXTURE_IMAGE_UNITS, 8 },
{ "max_fragment_uniform_vectors", "MAX_FRAGMENT_UNIFORM_VECTORS has a minimum value of 16", GL_MAX_FRAGMENT_UNIFORM_VECTORS, 16 },
{ "max_renderbuffer_size", "MAX_RENDERBUFFER_SIZE has a minimum value of 1", GL_MAX_RENDERBUFFER_SIZE, 1 },
};
// \note implementation defined limits have their own tests so just check the conversions to boolean and float
StateVerifier* implementationLimitVerifiers[] = {m_verifierBoolean, m_verifierFloat};
StateVerifier* normalVerifiers[] = {m_verifierBoolean, m_verifierInteger, m_verifierFloat};
for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(implementationMinLimits); testNdx++)
FOR_EACH_VERIFIER(implementationLimitVerifiers, addChild(new ConstantMinimumValueTestCase(m_context, verifier, (std::string(implementationMinLimits[testNdx].name) + verifier->getTestNamePostfix()).c_str(), implementationMinLimits[testNdx].description, implementationMinLimits[testNdx].targetName, implementationMinLimits[testNdx].value)));
FOR_EACH_VERIFIER(implementationLimitVerifiers, addChild(new SampleBuffersTestCase (m_context, verifier, (std::string("sample_buffers") + verifier->getTestNamePostfix()).c_str(), "SAMPLE_BUFFERS")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new SamplesTestCase (m_context, verifier, (std::string("samples") + verifier->getTestNamePostfix()).c_str(), "SAMPLES")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new HintTestCase (m_context, verifier, (std::string("generate_mipmap_hint") + verifier->getTestNamePostfix()).c_str(), "GENERATE_MIPMAP_HINT", GL_GENERATE_MIPMAP_HINT)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new DepthFuncTestCase (m_context, verifier, (std::string("depth_func") + verifier->getTestNamePostfix()).c_str(), "DEPTH_FUNC")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new CullFaceTestCase (m_context, verifier, (std::string("cull_face_mode") + verifier->getTestNamePostfix()).c_str(), "CULL_FACE_MODE")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new FrontFaceTestCase (m_context, verifier, (std::string("front_face_mode") + verifier->getTestNamePostfix()).c_str(), "FRONT_FACE")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new ViewPortTestCase (m_context, verifier, (std::string("viewport") + verifier->getTestNamePostfix()).c_str(), "VIEWPORT")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new ScissorBoxTestCase (m_context, verifier, (std::string("scissor_box") + verifier->getTestNamePostfix()).c_str(), "SCISSOR_BOX")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new MaxViewportDimsTestCase (m_context, verifier, (std::string("max_viewport_dims") + verifier->getTestNamePostfix()).c_str(), "MAX_VIEWPORT_DIMS")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new BufferComponentSizeCase (m_context, verifier, (std::string("buffer_component_size") + verifier->getTestNamePostfix()).c_str(), "x BITS")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilRefTestCase (m_context, verifier, (std::string("stencil_ref") + verifier->getTestNamePostfix()).c_str(), "STENCIL_REF", GL_STENCIL_REF)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilRefTestCase (m_context, verifier, (std::string("stencil_back_ref") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_REF", GL_STENCIL_BACK_REF)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilRefSeparateTestCase (m_context, verifier, (std::string("stencil_ref_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_REF (separate)", GL_STENCIL_REF, GL_FRONT)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilRefSeparateTestCase (m_context, verifier, (std::string("stencil_ref_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_REF (separate)", GL_STENCIL_REF, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilRefSeparateTestCase (m_context, verifier, (std::string("stencil_back_ref_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_REF (separate)", GL_STENCIL_BACK_REF, GL_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilRefSeparateTestCase (m_context, verifier, (std::string("stencil_back_ref_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_REF (separate)", GL_STENCIL_BACK_REF, GL_FRONT_AND_BACK)));
const struct NamedStencilOp
{
const char* name;
const char* frontDescription;
GLenum frontTarget;
const char* backDescription;
GLenum backTarget;
} stencilOps[] =
{
{ "fail", "STENCIL_FAIL", GL_STENCIL_FAIL, "STENCIL_BACK_FAIL", GL_STENCIL_BACK_FAIL },
{ "depth_fail", "STENCIL_PASS_DEPTH_FAIL", GL_STENCIL_PASS_DEPTH_FAIL, "STENCIL_BACK_PASS_DEPTH_FAIL", GL_STENCIL_BACK_PASS_DEPTH_FAIL },
{ "depth_pass", "STENCIL_PASS_DEPTH_PASS", GL_STENCIL_PASS_DEPTH_PASS, "STENCIL_BACK_PASS_DEPTH_PASS", GL_STENCIL_BACK_PASS_DEPTH_PASS }
};
for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(stencilOps); testNdx++)
{
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilOpTestCase (m_context, verifier, (std::string("stencil_") + stencilOps[testNdx].name + verifier->getTestNamePostfix()).c_str(), stencilOps[testNdx].frontDescription, stencilOps[testNdx].frontTarget)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilOpTestCase (m_context, verifier, (std::string("stencil_back_") + stencilOps[testNdx].name + verifier->getTestNamePostfix()).c_str(), stencilOps[testNdx].backDescription, stencilOps[testNdx].backTarget)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilOpSeparateTestCase (m_context, verifier, (std::string("stencil_") + stencilOps[testNdx].name + "_separate_both" + verifier->getTestNamePostfix()).c_str(), stencilOps[testNdx].frontDescription, stencilOps[testNdx].frontTarget, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilOpSeparateTestCase (m_context, verifier, (std::string("stencil_back_") + stencilOps[testNdx].name + "_separate_both" + verifier->getTestNamePostfix()).c_str(), stencilOps[testNdx].backDescription, stencilOps[testNdx].backTarget, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilOpSeparateTestCase (m_context, verifier, (std::string("stencil_") + stencilOps[testNdx].name + "_separate" + verifier->getTestNamePostfix()).c_str(), stencilOps[testNdx].frontDescription, stencilOps[testNdx].frontTarget, GL_FRONT)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilOpSeparateTestCase (m_context, verifier, (std::string("stencil_back_") + stencilOps[testNdx].name + "_separate" + verifier->getTestNamePostfix()).c_str(), stencilOps[testNdx].backDescription, stencilOps[testNdx].backTarget, GL_BACK)));
}
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilFuncTestCase (m_context, verifier, (std::string("stencil_func") + verifier->getTestNamePostfix()).c_str(), "STENCIL_FUNC")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilFuncSeparateTestCase (m_context, verifier, (std::string("stencil_func_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_FUNC (separate)", GL_STENCIL_FUNC, GL_FRONT)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilFuncSeparateTestCase (m_context, verifier, (std::string("stencil_func_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_FUNC (separate)", GL_STENCIL_FUNC, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilFuncSeparateTestCase (m_context, verifier, (std::string("stencil_back_func_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_FUNC (separate)", GL_STENCIL_BACK_FUNC, GL_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilFuncSeparateTestCase (m_context, verifier, (std::string("stencil_back_func_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_FUNC (separate)", GL_STENCIL_BACK_FUNC, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilMaskTestCase (m_context, verifier, (std::string("stencil_value_mask") + verifier->getTestNamePostfix()).c_str(), "STENCIL_VALUE_MASK", GL_STENCIL_VALUE_MASK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilMaskTestCase (m_context, verifier, (std::string("stencil_back_value_mask") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_VALUE_MASK", GL_STENCIL_BACK_VALUE_MASK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilMaskSeparateTestCase (m_context, verifier, (std::string("stencil_value_mask_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_VALUE_MASK (separate)", GL_STENCIL_VALUE_MASK, GL_FRONT)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilMaskSeparateTestCase (m_context, verifier, (std::string("stencil_value_mask_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_VALUE_MASK (separate)", GL_STENCIL_VALUE_MASK, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilMaskSeparateTestCase (m_context, verifier, (std::string("stencil_back_value_mask_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_VALUE_MASK (separate)", GL_STENCIL_BACK_VALUE_MASK, GL_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilMaskSeparateTestCase (m_context, verifier, (std::string("stencil_back_value_mask_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_VALUE_MASK (separate)", GL_STENCIL_BACK_VALUE_MASK, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilWriteMaskTestCase (m_context, verifier, (std::string("stencil_writemask") + verifier->getTestNamePostfix()).c_str(), "STENCIL_WRITEMASK", GL_STENCIL_WRITEMASK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilWriteMaskTestCase (m_context, verifier, (std::string("stencil_back_writemask") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_WRITEMASK", GL_STENCIL_BACK_WRITEMASK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilWriteMaskSeparateTestCase (m_context, verifier, (std::string("stencil_writemask_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_WRITEMASK (separate)", GL_STENCIL_WRITEMASK, GL_FRONT)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilWriteMaskSeparateTestCase (m_context, verifier, (std::string("stencil_writemask_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_WRITEMASK (separate)", GL_STENCIL_WRITEMASK, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilWriteMaskSeparateTestCase (m_context, verifier, (std::string("stencil_back_writemask_separate") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_WRITEMASK (separate)", GL_STENCIL_BACK_WRITEMASK, GL_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilWriteMaskSeparateTestCase (m_context, verifier, (std::string("stencil_back_writemask_separate_both") + verifier->getTestNamePostfix()).c_str(), "STENCIL_BACK_WRITEMASK (separate)", GL_STENCIL_BACK_WRITEMASK, GL_FRONT_AND_BACK)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new PixelStoreAlignTestCase(m_context, verifier, (std::string("unpack_alignment") + verifier->getTestNamePostfix()).c_str(), "UNPACK_ALIGNMENT", GL_UNPACK_ALIGNMENT)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new PixelStoreAlignTestCase(m_context, verifier, (std::string("pack_alignment") + verifier->getTestNamePostfix()).c_str(), "PACK_ALIGNMENT", GL_PACK_ALIGNMENT)));
{
const struct BlendColorState
{
const char* name;
const char* description;
GLenum target;
int initialValue;
} blendColorStates[] =
{
{ "blend_src_rgb", "BLEND_SRC_RGB", GL_BLEND_SRC_RGB, GL_ONE },
{ "blend_src_alpha", "BLEND_SRC_ALPHA", GL_BLEND_SRC_ALPHA, GL_ONE },
{ "blend_dst_rgb", "BLEND_DST_RGB", GL_BLEND_DST_RGB, GL_ZERO },
{ "blend_dst_alpha", "BLEND_DST_ALPHA", GL_BLEND_DST_ALPHA, GL_ZERO }
};
for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(blendColorStates); testNdx++)
{
FOR_EACH_VERIFIER(normalVerifiers, addChild(new BlendFuncTestCase (m_context, verifier, (std::string(blendColorStates[testNdx].name) + verifier->getTestNamePostfix()).c_str(), blendColorStates[testNdx].description, blendColorStates[testNdx].target, blendColorStates[testNdx].initialValue)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new BlendFuncSeparateTestCase (m_context, verifier, (std::string(blendColorStates[testNdx].name) + "_separate" + verifier->getTestNamePostfix()).c_str(), blendColorStates[testNdx].description, blendColorStates[testNdx].target, blendColorStates[testNdx].initialValue)));
}
}
{
const struct BlendEquationState
{
const char* name;
const char* description;
GLenum target;
int initialValue;
} blendEquationStates[] =
{
{ "blend_equation_rgb", "BLEND_EQUATION_RGB", GL_BLEND_EQUATION_RGB, GL_FUNC_ADD },
{ "blend_equation_alpha", "BLEND_EQUATION_ALPHA", GL_BLEND_EQUATION_ALPHA, GL_FUNC_ADD }
};
for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(blendEquationStates); testNdx++)
{
FOR_EACH_VERIFIER(normalVerifiers, addChild(new BlendEquationTestCase (m_context, verifier, (std::string(blendEquationStates[testNdx].name) + + verifier->getTestNamePostfix()).c_str(), blendEquationStates[testNdx].description, blendEquationStates[testNdx].target, blendEquationStates[testNdx].initialValue)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new BlendEquationSeparateTestCase (m_context, verifier, (std::string(blendEquationStates[testNdx].name) + "_separate" + verifier->getTestNamePostfix()).c_str(), blendEquationStates[testNdx].description, blendEquationStates[testNdx].target, blendEquationStates[testNdx].initialValue)));
}
}
FOR_EACH_VERIFIER(normalVerifiers, addChild(new ImplementationArrayTestCase (m_context, verifier, (std::string("compressed_texture_formats") + verifier->getTestNamePostfix()).c_str(), "COMPRESSED_TEXTURE_FORMATS", GL_COMPRESSED_TEXTURE_FORMATS, GL_NUM_COMPRESSED_TEXTURE_FORMATS, 0)));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new ImplementationArrayTestCase (m_context, verifier, (std::string("shader_binary_formats") + verifier->getTestNamePostfix()).c_str(), "SHADER_BINARY_FORMATS", GL_SHADER_BINARY_FORMATS, GL_NUM_SHADER_BINARY_FORMATS, 0)));
FOR_EACH_QUERYTYPE(queryTypes, addChild(new BufferBindingTestCase (m_context, queryType, (std::string("array_buffer_binding") + getQueryTypeSuffix(queryType)).c_str(), "ARRAY_BUFFER_BINDING", GL_ARRAY_BUFFER_BINDING, GL_ARRAY_BUFFER)));
FOR_EACH_QUERYTYPE(queryTypes, addChild(new BufferBindingTestCase (m_context, queryType, (std::string("element_array_buffer_binding") + getQueryTypeSuffix(queryType)).c_str(), "ELEMENT_ARRAY_BUFFER_BINDING", GL_ELEMENT_ARRAY_BUFFER_BINDING, GL_ELEMENT_ARRAY_BUFFER)));
FOR_EACH_QUERYTYPE(queryTypes, addChild(new CurrentProgramBindingTestCase (m_context, queryType, (std::string("current_program_binding") + getQueryTypeSuffix(queryType)).c_str(), "CURRENT_PROGRAM")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new StencilClearValueTestCase (m_context, verifier, (std::string("stencil_clear_value") + verifier->getTestNamePostfix()).c_str(), "STENCIL_CLEAR_VALUE")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new ActiveTextureTestCase (m_context, verifier, (std::string("active_texture") + verifier->getTestNamePostfix()).c_str(), "ACTIVE_TEXTURE")));
FOR_EACH_QUERYTYPE(queryTypes, addChild(new RenderbufferBindingTestCase (m_context, queryType, (std::string("renderbuffer_binding") + getQueryTypeSuffix(queryType)).c_str(), "RENDERBUFFER_BINDING")));
FOR_EACH_QUERYTYPE(queryTypes, addChild(new TextureBindingTestCase (m_context, queryType, (std::string("texture_binding_2d") + getQueryTypeSuffix(queryType)).c_str(), "TEXTURE_BINDING_2D", GL_TEXTURE_BINDING_2D, GL_TEXTURE_2D)));
FOR_EACH_QUERYTYPE(queryTypes, addChild(new TextureBindingTestCase (m_context, queryType, (std::string("texture_binding_cube_map") + getQueryTypeSuffix(queryType)).c_str(), "TEXTURE_BINDING_CUBE_MAP", GL_TEXTURE_BINDING_CUBE_MAP, GL_TEXTURE_CUBE_MAP)));
FOR_EACH_QUERYTYPE(queryTypes, addChild(new FrameBufferBindingTestCase (m_context, queryType, (std::string("framebuffer_binding") + getQueryTypeSuffix(queryType)).c_str(), "DRAW_FRAMEBUFFER_BINDING and READ_FRAMEBUFFER_BINDING")));
FOR_EACH_VERIFIER(normalVerifiers, addChild(new ImplementationColorReadTestCase (m_context, verifier, (std::string("implementation_color_read") + verifier->getTestNamePostfix()).c_str(), "IMPLEMENTATION_COLOR_READ_TYPE and IMPLEMENTATION_COLOR_READ_FORMAT")));
}
void IntegerStateQueryTests::deinit (void)
{
if (m_verifierBoolean)
{
delete m_verifierBoolean;
m_verifierBoolean = DE_NULL;
}
if (m_verifierInteger)
{
delete m_verifierInteger;
m_verifierInteger = DE_NULL;
}
if (m_verifierFloat)
{
delete m_verifierFloat;
m_verifierFloat = DE_NULL;
}
this->TestCaseGroup::deinit();
}
} // Functional
} // gles2
} // deqp