#ifndef _GLSSTATEQUERYUTIL_HPP #define _GLSSTATEQUERYUTIL_HPP /*------------------------------------------------------------------------- * drawElements Quality Program OpenGL (ES) 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 test utils. *//*--------------------------------------------------------------------*/ #include "tcuDefs.hpp" #include "tcuTestLog.hpp" #include "tcuTestContext.hpp" #include "tcuResultCollector.hpp" #include "glwDefs.hpp" #include "deMath.h" namespace glu { class CallLogWrapper; } // namespace glu namespace deqp { namespace gls { namespace StateQueryUtil { #define GLS_COLLECT_GL_ERROR(RES, ERR, MSG) \ do \ { \ const uint32_t err = (ERR); \ if (err != GL_NO_ERROR) \ (RES).fail(std::string("Got Error ") + glu::getErrorStr(err).toString() + ": " + (MSG)); \ } while (false) /*--------------------------------------------------------------------*//*! * \brief Rounds given float to the nearest integer (half up). * * Returns the nearest integer for a float argument. In the case that there * are two nearest integers at the equal distance (aka. the argument is of * form x.5), the integer with the higher value is chosen. (x.5 rounds to x+1) *//*--------------------------------------------------------------------*/ template T roundGLfloatToNearestIntegerHalfUp(float val) { return (T)(deFloatFloor(val + 0.5f)); } /*--------------------------------------------------------------------*//*! * \brief Rounds given float to the nearest integer (half down). * * Returns the nearest integer for a float argument. In the case that there * are two nearest integers at the equal distance (aka. the argument is of * form x.5), the integer with the higher value is chosen. (x.5 rounds to x) *//*--------------------------------------------------------------------*/ template T roundGLfloatToNearestIntegerHalfDown(float val) { return (T)(deFloatCeil(val - 0.5f)); } template class StateQueryMemoryWriteGuard { public: StateQueryMemoryWriteGuard(void); operator T &(void); T *operator&(void); bool isUndefined(void) const; bool isMemoryContaminated(void) const; bool isPreguardContaminated(void) const; bool isPostguardContaminated(void) const; bool verifyValidity(tcu::TestContext &testCtx) const; bool verifyValidity(tcu::ResultCollector &result) const; const T &get(void) const { return m_value; } private: enum { WRITE_GUARD_VALUE = 0xDE }; T m_preguard; T m_value; T m_postguard; // \note guards are not const qualified since the GL implementation might modify them }; template StateQueryMemoryWriteGuard::StateQueryMemoryWriteGuard(void) { DE_STATIC_ASSERT(sizeof(T) * 3 == sizeof(StateQueryMemoryWriteGuard)); // tightly packed deMemset(&m_preguard, WRITE_GUARD_VALUE, sizeof(m_preguard)); deMemset(&m_value, WRITE_GUARD_VALUE, sizeof(m_value)); deMemset(&m_postguard, WRITE_GUARD_VALUE, sizeof(m_postguard)); } template StateQueryMemoryWriteGuard::operator T &(void) { return m_value; } template T *StateQueryMemoryWriteGuard::operator&(void) { return &m_value; } template bool StateQueryMemoryWriteGuard::isUndefined() const { for (size_t i = 0; i < sizeof(T); ++i) if (((uint8_t *)&m_value)[i] != (uint8_t)WRITE_GUARD_VALUE) return false; return true; } template bool StateQueryMemoryWriteGuard::isMemoryContaminated() const { return isPreguardContaminated() || isPostguardContaminated(); } template bool StateQueryMemoryWriteGuard::isPreguardContaminated(void) const { for (size_t i = 0; i < sizeof(T); ++i) if (((uint8_t *)&m_preguard)[i] != (uint8_t)WRITE_GUARD_VALUE) return true; return false; } template bool StateQueryMemoryWriteGuard::isPostguardContaminated(void) const { for (size_t i = 0; i < sizeof(T); ++i) if (((uint8_t *)&m_postguard)[i] != (uint8_t)WRITE_GUARD_VALUE) return true; return false; } template bool StateQueryMemoryWriteGuard::verifyValidity(tcu::TestContext &testCtx) const { using tcu::TestLog; if (isPreguardContaminated()) { testCtx.getLog() << TestLog::Message << "// ERROR: Pre-guard value was modified " << TestLog::EndMessage; if (testCtx.getTestResult() == QP_TEST_RESULT_PASS || testCtx.getTestResult() == QP_TEST_RESULT_LAST) testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write"); return false; } else if (isPostguardContaminated()) { testCtx.getLog() << TestLog::Message << "// ERROR: Post-guard value was modified " << TestLog::EndMessage; if (testCtx.getTestResult() == QP_TEST_RESULT_PASS || testCtx.getTestResult() == QP_TEST_RESULT_LAST) testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write"); return false; } else if (isUndefined()) { testCtx.getLog() << TestLog::Message << "// ERROR: Get* did not return a value" << TestLog::EndMessage; if (testCtx.getTestResult() == QP_TEST_RESULT_PASS || testCtx.getTestResult() == QP_TEST_RESULT_LAST) testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did not return a value"); return false; } return true; } template bool StateQueryMemoryWriteGuard::verifyValidity(tcu::ResultCollector &result) const { using tcu::TestLog; if (isPreguardContaminated()) { result.fail("pre-guard value was modified"); return false; } else if (isPostguardContaminated()) { result.fail("post-guard value was modified"); return false; } else if (isUndefined()) { result.fail("Get* did not return a value"); return false; } return true; } template std::ostream &operator<<(std::ostream &str, const StateQueryMemoryWriteGuard &guard) { return str << guard.get(); } // Verifiers enum QueryType { QUERY_BOOLEAN = 0, QUERY_BOOLEAN_VEC4, QUERY_ISENABLED, QUERY_INTEGER, QUERY_INTEGER64, QUERY_FLOAT, // indexed QUERY_INDEXED_BOOLEAN, QUERY_INDEXED_BOOLEAN_VEC4, QUERY_INDEXED_ISENABLED, QUERY_INDEXED_INTEGER, QUERY_INDEXED_INTEGER_VEC4, QUERY_INDEXED_INTEGER64, QUERY_INDEXED_INTEGER64_VEC4, // attributes QUERY_ATTRIBUTE_INTEGER, QUERY_ATTRIBUTE_FLOAT, QUERY_ATTRIBUTE_PURE_INTEGER, QUERY_ATTRIBUTE_PURE_UNSIGNED_INTEGER, // fb QUERY_FRAMEBUFFER_INTEGER, // program QUERY_PROGRAM_INTEGER, QUERY_PROGRAM_INTEGER_VEC3, // program pipeline QUERY_PIPELINE_INTEGER, // texture param QUERY_TEXTURE_PARAM_INTEGER, QUERY_TEXTURE_PARAM_FLOAT, QUERY_TEXTURE_PARAM_PURE_INTEGER, QUERY_TEXTURE_PARAM_PURE_UNSIGNED_INTEGER, QUERY_TEXTURE_PARAM_INTEGER_VEC4, QUERY_TEXTURE_PARAM_FLOAT_VEC4, QUERY_TEXTURE_PARAM_PURE_INTEGER_VEC4, QUERY_TEXTURE_PARAM_PURE_UNSIGNED_INTEGER_VEC4, // texture level QUERY_TEXTURE_LEVEL_INTEGER, QUERY_TEXTURE_LEVEL_FLOAT, // pointer QUERY_POINTER, // object states QUERY_ISTEXTURE, // query queries QUERY_QUERY, // sampler state QUERY_SAMPLER_PARAM_INTEGER, QUERY_SAMPLER_PARAM_FLOAT, QUERY_SAMPLER_PARAM_PURE_INTEGER, QUERY_SAMPLER_PARAM_PURE_UNSIGNED_INTEGER, QUERY_SAMPLER_PARAM_INTEGER_VEC4, QUERY_SAMPLER_PARAM_FLOAT_VEC4, QUERY_SAMPLER_PARAM_PURE_INTEGER_VEC4, QUERY_SAMPLER_PARAM_PURE_UNSIGNED_INTEGER_VEC4, QUERY_LAST }; enum DataType { DATATYPE_BOOLEAN = 0, DATATYPE_INTEGER, DATATYPE_INTEGER64, DATATYPE_FLOAT16, DATATYPE_FLOAT, DATATYPE_UNSIGNED_INTEGER, DATATYPE_INTEGER_VEC3, DATATYPE_FLOAT_VEC4, DATATYPE_INTEGER_VEC4, DATATYPE_INTEGER64_VEC4, DATATYPE_UNSIGNED_INTEGER_VEC4, DATATYPE_BOOLEAN_VEC4, DATATYPE_POINTER, DATATYPE_LAST }; class QueriedState { public: typedef glw::GLint GLIntVec3[3]; typedef glw::GLint GLIntVec4[4]; typedef glw::GLuint GLUintVec4[4]; typedef glw::GLfloat GLFloatVec4[4]; typedef bool BooleanVec4[4]; typedef glw::GLint64 GLInt64Vec4[4]; QueriedState(void); explicit QueriedState(glw::GLint); explicit QueriedState(glw::GLint64); explicit QueriedState(bool); explicit QueriedState(glw::GLfloat); explicit QueriedState(glw::GLuint); explicit QueriedState(const GLIntVec3 &); explicit QueriedState(void *); explicit QueriedState(const GLIntVec4 &); explicit QueriedState(const GLUintVec4 &); explicit QueriedState(const GLFloatVec4 &); explicit QueriedState(const BooleanVec4 &); explicit QueriedState(const GLInt64Vec4 &); bool isUndefined(void) const; DataType getType(void) const; glw::GLint &getIntAccess(void); glw::GLint64 &getInt64Access(void); bool &getBoolAccess(void); glw::GLfloat &getFloatAccess(void); glw::GLuint &getUintAccess(void); GLIntVec3 &getIntVec3Access(void); void *&getPtrAccess(void); GLIntVec4 &getIntVec4Access(void); GLUintVec4 &getUintVec4Access(void); GLFloatVec4 &getFloatVec4Access(void); BooleanVec4 &getBooleanVec4Access(void); GLInt64Vec4 &getInt64Vec4Access(void); private: DataType m_type; union { glw::GLint vInt; glw::GLint64 vInt64; bool vBool; glw::GLfloat vFloat; glw::GLuint vUint; GLIntVec3 vIntVec3; void *vPtr; GLIntVec4 vIntVec4; GLUintVec4 vUintVec4; GLFloatVec4 vFloatVec4; BooleanVec4 vBooleanVec4; GLInt64Vec4 vInt64Vec4; } m_v; }; // query functions void queryState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum pname, QueriedState &state); void queryIndexedState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum target, int index, QueriedState &state); void queryAttributeState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum target, int index, QueriedState &state); void queryFramebufferState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState &state); void queryProgramState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLuint program, glw::GLenum pname, QueriedState &state); void queryPipelineState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLuint pipeline, glw::GLenum pname, QueriedState &state); void queryTextureParamState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState &state); void queryTextureLevelState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum target, int level, glw::GLenum pname, QueriedState &state); void queryPointerState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum pname, QueriedState &state); void queryObjectState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLuint handle, QueriedState &state); void queryQueryState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState &state); void querySamplerState(tcu::ResultCollector &result, glu::CallLogWrapper &gl, QueryType type, glw::GLuint sampler, glw::GLenum pname, QueriedState &state); // verification functions void verifyBoolean(tcu::ResultCollector &result, QueriedState &state, bool expected); void verifyInteger(tcu::ResultCollector &result, QueriedState &state, int expected); void verifyIntegerMin(tcu::ResultCollector &result, QueriedState &state, int minValue); void verifyIntegerMax(tcu::ResultCollector &result, QueriedState &state, int maxValue); void verifyIntegersEqual(tcu::ResultCollector &result, QueriedState &stateA, QueriedState &stateB); void verifyFloat(tcu::ResultCollector &result, QueriedState &state, float expected); void verifyFloatMin(tcu::ResultCollector &result, QueriedState &state, float minValue); void verifyFloatMax(tcu::ResultCollector &result, QueriedState &state, float maxValue); void verifyIntegerVec3(tcu::ResultCollector &result, QueriedState &state, const tcu::IVec3 &expected); void verifyIntegerVec4(tcu::ResultCollector &result, QueriedState &state, const tcu::IVec4 &expected); void verifyUnsignedIntegerVec4(tcu::ResultCollector &result, QueriedState &state, const tcu::UVec4 &expected); void verifyFloatVec4(tcu::ResultCollector &result, QueriedState &state, const tcu::Vec4 &expected); void verifyBooleanVec4(tcu::ResultCollector &result, QueriedState &state, const tcu::BVec4 &expected); void verifyPointer(tcu::ResultCollector &result, QueriedState &state, const void *expected); void verifyNormalizedI32Vec4(tcu::ResultCollector &result, QueriedState &state, const tcu::IVec4 &expected); // Helper functions that both query and verify void verifyStateBoolean(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, bool expected, QueryType type); void verifyStateInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int expected, QueryType type); void verifyStateIntegerMin(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int minValue, QueryType type); void verifyStateIntegerMax(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int maxValue, QueryType type); void verifyStateIntegerEqualToOther(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum other, QueryType type); void verifyStateFloat(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, float reference, QueryType type); void verifyStateFloatMin(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, float minValue, QueryType type); void verifyStateFloatMax(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, float maxValue, QueryType type); void verifyStatePointer(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, const void *expected, QueryType type); void verifyStateIndexedBoolean(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int index, bool expected, QueryType type); void verifyStateIndexedBooleanVec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int index, const tcu::BVec4 &expected, QueryType type); void verifyStateIndexedInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int index, int expected, QueryType type); void verifyStateIndexedIntegerMin(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int index, int minValue, QueryType type); void verifyStateAttributeInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int index, int expected, QueryType type); void verifyStateFramebufferInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, int expected, QueryType type); void verifyStateFramebufferIntegerMin(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, int minValue, QueryType type); void verifyStateProgramInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint program, glw::GLenum pname, int expected, QueryType type); void verifyStateProgramIntegerVec3(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint program, glw::GLenum pname, const tcu::IVec3 &expected, QueryType type); void verifyStatePipelineInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint pipeline, glw::GLenum pname, int expected, QueryType type); void verifyStateTextureParamInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, int expected, QueryType type); void verifyStateTextureParamFloat(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, float expected, QueryType type); void verifyStateTextureParamFloatVec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, const tcu::Vec4 &expected, QueryType type); void verifyStateTextureParamNormalizedI32Vec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, const tcu::IVec4 &expected, QueryType type); void verifyStateTextureParamIntegerVec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, const tcu::IVec4 &expected, QueryType type); void verifyStateTextureParamUnsignedIntegerVec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, const tcu::UVec4 &expected, QueryType type); void verifyStateTextureLevelInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, int level, glw::GLenum pname, int expected, QueryType type); void verifyStateObjectBoolean(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint handle, bool expected, QueryType type); void verifyStateQueryInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLenum target, glw::GLenum pname, int expected, QueryType type); void verifyStateSamplerParamInteger(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint sampler, glw::GLenum pname, int expected, QueryType type); void verifyStateSamplerParamFloat(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint sampler, glw::GLenum pname, float expected, QueryType type); void verifyStateSamplerParamFloatVec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint sampler, glw::GLenum pname, const tcu::Vec4 &expected, QueryType type); void verifyStateSamplerParamNormalizedI32Vec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint sampler, glw::GLenum pname, const tcu::IVec4 &expected, QueryType type); void verifyStateSamplerParamIntegerVec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint sampler, glw::GLenum pname, const tcu::IVec4 &expected, QueryType type); void verifyStateSamplerParamUnsignedIntegerVec4(tcu::ResultCollector &result, glu::CallLogWrapper &gl, glw::GLuint sampler, glw::GLenum pname, const tcu::UVec4 &expected, QueryType type); } // namespace StateQueryUtil } // namespace gls } // namespace deqp #endif // _GLSSTATEQUERYUTIL_HPP