blob: 433b1c223f61e252176b22be34c33a0dd5c7e8fc [file] [log] [blame]
/*-------------------------------------------------------------------------
* drawElements Quality Program OpenGL ES 3.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 Integer64 State Query tests.
*//*--------------------------------------------------------------------*/
#include "es3fInteger64StateQueryTests.hpp"
#include "glsStateQueryUtil.hpp"
#include "es3fApiCase.hpp"
#include "gluRenderContext.hpp"
#include "tcuRenderTarget.hpp"
#include "glwEnums.hpp"
#include <limits>
using namespace glw; // GLint and other
using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
namespace deqp
{
namespace gles3
{
namespace Functional
{
namespace Integer64StateQueryVerifiers
{
// 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 verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext &testCtx, GLenum name, GLuint64 reference) = 0;
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 verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext &testCtx, GLenum name, GLuint64 reference);
};
GetBooleanVerifier::GetBooleanVerifier(const glw::Functions &gl, tcu::TestLog &log)
: StateVerifier(gl, log, "_getboolean")
{
}
void GetBooleanVerifier::verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext &testCtx, GLenum name,
GLuint64 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");
}
}
//GetIntegerVerifier
class GetIntegerVerifier : public StateVerifier
{
public:
GetIntegerVerifier(const glw::Functions &gl, tcu::TestLog &log);
void verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext &testCtx, GLenum name, GLuint64 reference);
};
GetIntegerVerifier::GetIntegerVerifier(const glw::Functions &gl, tcu::TestLog &log)
: StateVerifier(gl, log, "_getinteger")
{
}
void GetIntegerVerifier::verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext &testCtx, GLenum name,
GLuint64 reference)
{
using tcu::TestLog;
StateQueryMemoryWriteGuard<GLint> state;
glGetIntegerv(name, &state);
if (!state.verifyValidity(testCtx))
return;
// check that the converted value would be in the correct range, otherwise checking wont tell us anything
if (reference > (GLuint64)std::numeric_limits<GLint>::max())
return;
if (GLuint(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");
}
}
//GetFloatVerifier
class GetFloatVerifier : public StateVerifier
{
public:
GetFloatVerifier(const glw::Functions &gl, tcu::TestLog &log);
void verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext &testCtx, GLenum name, GLuint64 reference);
};
GetFloatVerifier::GetFloatVerifier(const glw::Functions &gl, tcu::TestLog &log) : StateVerifier(gl, log, "_getfloat")
{
}
void GetFloatVerifier::verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext &testCtx, GLenum name, GLuint64 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");
}
}
} // namespace Integer64StateQueryVerifiers
namespace
{
using namespace Integer64StateQueryVerifiers;
class ConstantMinimumValue64TestCase : public ApiCase
{
public:
ConstantMinimumValue64TestCase(Context &context, StateVerifier *verifier, const char *name, const char *description,
GLenum targetName, GLuint64 minValue)
: ApiCase(context, name, description)
, m_targetName(targetName)
, m_minValue(minValue)
, m_verifier(verifier)
{
}
void test(void)
{
m_verifier->verifyUnsignedInteger64GreaterOrEqual(m_testCtx, m_targetName, m_minValue);
expectError(GL_NO_ERROR);
}
private:
GLenum m_targetName;
GLuint64 m_minValue;
StateVerifier *m_verifier;
};
class MaxCombinedStageUniformComponentsCase : public ApiCase
{
public:
MaxCombinedStageUniformComponentsCase(Context &context, StateVerifier *verifier, const char *name,
const char *description, GLenum targetName, GLenum targetMaxUniformBlocksName,
GLenum targetMaxUniformComponentsName)
: ApiCase(context, name, description)
, m_targetName(targetName)
, m_targetMaxUniformBlocksName(targetMaxUniformBlocksName)
, m_targetMaxUniformComponentsName(targetMaxUniformComponentsName)
, m_verifier(verifier)
{
}
void test(void)
{
GLint uniformBlockSize = 0;
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &uniformBlockSize);
expectError(GL_NO_ERROR);
GLint maxUniformBlocks = 0;
GLint maxUniformComponents = 0;
glGetIntegerv(m_targetMaxUniformBlocksName, &maxUniformBlocks);
glGetIntegerv(m_targetMaxUniformComponentsName, &maxUniformComponents);
expectError(GL_NO_ERROR);
// MAX_stage_UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE / 4 + MAX_stage_UNIFORM_COMPONENTS
const GLuint64 minCombinedUniformComponents =
GLuint64(maxUniformBlocks) * uniformBlockSize / 4 + maxUniformComponents;
m_verifier->verifyUnsignedInteger64GreaterOrEqual(m_testCtx, m_targetName, minCombinedUniformComponents);
expectError(GL_NO_ERROR);
}
private:
GLenum m_targetName;
GLenum m_targetMaxUniformBlocksName;
GLenum m_targetMaxUniformComponentsName;
StateVerifier *m_verifier;
};
#define FOR_EACH_VERIFIER(VERIFIERS, CODE_BLOCK) \
do \
{ \
for (int _verifierNdx = 0; _verifierNdx < DE_LENGTH_OF_ARRAY(VERIFIERS); _verifierNdx++) \
{ \
StateVerifier *verifier = (VERIFIERS)[_verifierNdx]; \
CODE_BLOCK; \
} \
} while (0)
} // namespace
Integer64StateQueryTests::Integer64StateQueryTests(Context &context)
: TestCaseGroup(context, "integers64", "Integer (64) Values")
, m_verifierBoolean(DE_NULL)
, m_verifierInteger(DE_NULL)
, m_verifierFloat(DE_NULL)
{
}
Integer64StateQueryTests::~Integer64StateQueryTests(void)
{
deinit();
}
void Integer64StateQueryTests::init(void)
{
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 LimitedStateInteger64
{
const char *name;
const char *description;
GLenum targetName;
GLuint64 minValue;
} implementationLimits[] = {{"max_element_index", "MAX_ELEMENT_INDEX", GL_MAX_ELEMENT_INDEX, 0x00FFFFFF /*2^24-1*/},
{"max_server_wait_timeout", "MAX_SERVER_WAIT_TIMEOUT", GL_MAX_SERVER_WAIT_TIMEOUT, 0},
{"max_uniform_block_size", "MAX_UNIFORM_BLOCK_SIZE", GL_MAX_UNIFORM_BLOCK_SIZE, 16384}};
// \note do not check the values with integer64 verifier as that has already been checked in implementation_limits
StateVerifier *verifiers[] = {m_verifierBoolean, m_verifierInteger, m_verifierFloat};
for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(implementationLimits); testNdx++)
FOR_EACH_VERIFIER(
verifiers, addChild(new ConstantMinimumValue64TestCase(
m_context, verifier,
(std::string(implementationLimits[testNdx].name) + verifier->getTestNamePostfix()).c_str(),
implementationLimits[testNdx].description, implementationLimits[testNdx].targetName,
implementationLimits[testNdx].minValue)));
FOR_EACH_VERIFIER(
verifiers, addChild(new MaxCombinedStageUniformComponentsCase(
m_context, verifier,
(std::string("max_combined_vertex_uniform_components") + verifier->getTestNamePostfix()).c_str(),
"MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,
GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_VERTEX_UNIFORM_COMPONENTS)));
FOR_EACH_VERIFIER(
verifiers,
addChild(new MaxCombinedStageUniformComponentsCase(
m_context, verifier,
(std::string("max_combined_fragment_uniform_components") + verifier->getTestNamePostfix()).c_str(),
"MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,
GL_MAX_FRAGMENT_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS)));
}
void Integer64StateQueryTests::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();
}
} // namespace Functional
} // namespace gles3
} // namespace deqp