| /*------------------------------------------------------------------------- |
| * 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 State Query tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es3fIntegerStateQueryTests.hpp" |
| #include "es3fApiCase.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 gles3 |
| { |
| 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 verifyIntegerLessOrEqual (tcu::TestContext& testCtx, GLenum name, GLint 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 verifyIntegerLessOrEqual (tcu::TestContext& testCtx, GLenum name, GLint 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::verifyIntegerLessOrEqual (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 less than reference (correct) |
| return; |
| |
| if (state == GL_FALSE) // state is zero |
| { |
| if (reference < 0) // and reference is less 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 verifyIntegerLessOrEqual (tcu::TestContext& testCtx, GLenum name, GLint 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::verifyIntegerLessOrEqual (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 less 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::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"); |
| } |
| } |
| |
| //GetInteger64Verifier |
| |
| class GetInteger64Verifier : public StateVerifier |
| { |
| public: |
| GetInteger64Verifier (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 verifyIntegerLessOrEqual (tcu::TestContext& testCtx, GLenum name, GLint 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); |
| }; |
| |
| GetInteger64Verifier::GetInteger64Verifier (const glw::Functions& gl, tcu::TestLog& log) |
| : StateVerifier(gl, log, "_getinteger64") |
| { |
| } |
| |
| void GetInteger64Verifier::verifyInteger (tcu::TestContext& testCtx, GLenum name, GLint reference) |
| { |
| using tcu::TestLog; |
| |
| StateQueryMemoryWriteGuard<GLint64> state; |
| glGetInteger64v(name, &state); |
| |
| if (!state.verifyValidity(testCtx)) |
| return; |
| |
| if (state != GLint64(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 GetInteger64Verifier::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 GetInteger64Verifier::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<GLint64[4]> intVector4; |
| glGetInteger64v(name, intVector4); |
| |
| if (!intVector4.verifyValidity(testCtx)) |
| return; |
| |
| if ((enableRef0 && (intVector4[0] != GLint64(reference0))) || |
| (enableRef1 && (intVector4[1] != GLint64(reference1))) || |
| (enableRef2 && (intVector4[2] != GLint64(reference2))) || |
| (enableRef3 && (intVector4[3] != GLint64(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 GetInteger64Verifier::verifyIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference) |
| { |
| using tcu::TestLog; |
| |
| StateQueryMemoryWriteGuard<GLint64> state; |
| glGetInteger64v(name, &state); |
| |
| if (!state.verifyValidity(testCtx)) |
| return; |
| |
| if (state < GLint64(reference)) |
| { |
| testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << GLint64(reference) << "; got " << state << TestLog::EndMessage; |
| if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) |
| testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value"); |
| } |
| } |
| |
| void GetInteger64Verifier::verifyUnsignedIntegerGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint reference) |
| { |
| using tcu::TestLog; |
| |
| StateQueryMemoryWriteGuard<GLint64> state; |
| glGetInteger64v(name, &state); |
| |
| if (!state.verifyValidity(testCtx)) |
| return; |
| |
| if (GLuint(state) < GLint64(reference)) |
| { |
| testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << GLint64(reference) << "; got " << GLuint(state) << TestLog::EndMessage; |
| if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) |
| testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value"); |
| } |
| } |
| |
| void GetInteger64Verifier::verifyIntegerLessOrEqual (tcu::TestContext& testCtx, GLenum name, GLint reference) |
| { |
| using tcu::TestLog; |
| |
| StateQueryMemoryWriteGuard<GLint64> state; |
| glGetInteger64v(name, &state); |
| |
| if (!state.verifyValidity(testCtx)) |
| return; |
| |
| if (state > GLint64(reference)) |
| { |
| testCtx.getLog() << TestLog::Message << "// ERROR: expected less or equal to " << GLint64(reference) << "; got " << state << TestLog::EndMessage; |
| if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) |
| testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value"); |
| } |
| } |
| |
| void GetInteger64Verifier::verifyIntegerGreaterOrEqual2 (tcu::TestContext& testCtx, GLenum name, GLint reference0, GLint reference1) |
| { |
| using tcu::TestLog; |
| |
| StateQueryMemoryWriteGuard<GLint64[2]> intVector2; |
| glGetInteger64v(name, intVector2); |
| |
| if (!intVector2.verifyValidity(testCtx)) |
| return; |
| |
| if (intVector2[0] < GLint64(reference0) || intVector2[1] < GLint64(reference1)) |
| { |
| testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << GLint64(reference0) << ", " << GLint64(reference1) << "; got " << intVector2[0] << ", " << intVector2[1] << TestLog::EndMessage; |
| if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) |
| testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value"); |
| } |
| } |
| |
| void GetInteger64Verifier::verifyIntegerAnyOf (tcu::TestContext& testCtx, GLenum name, const GLint references[], size_t referencesLength) |
| { |
| using tcu::TestLog; |
| |
| StateQueryMemoryWriteGuard<GLint64> state; |
| glGetInteger64v(name, &state); |
| |
| if (!state.verifyValidity(testCtx)) |
| return; |
| |
| for (size_t ndx = 0; ndx < referencesLength; ++ndx) |
| { |
| const GLint64 expectedGLState = GLint64(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 GetInteger64Verifier::verifyStencilMaskInitial (tcu::TestContext& testCtx, GLenum name, int stencilBits) |
| { |
| using tcu::TestLog; |
| |
| StateQueryMemoryWriteGuard<GLint64> state; |
| glGetInteger64v(name, &state); |
| |
| if (!state.verifyValidity(testCtx)) |
| return; |
| |
| const GLint64 reference = (1ULL << stencilBits) - 1; |
| |
| if ((state & reference) != reference) // the least significant stencilBits bits should be on |
| { |
| testCtx.getLog() << TestLog::Message << "// ERROR: expected mimimum 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 verifyIntegerLessOrEqual (tcu::TestContext& testCtx, GLenum name, GLint 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::verifyIntegerLessOrEqual (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 less 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 ConstantMaximumValueTestCase : public ApiCase |
| { |
| public: |
| ConstantMaximumValueTestCase (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->verifyIntegerLessOrEqual(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 of first two values |
| m_verifier->verifyInteger4Mask(m_testCtx, GL_SCISSOR_BOX, 0, true, 0, true, 0, false, 0, false); |
| 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 PixelStoreTestCase : public ApiCase |
| { |
| public: |
| PixelStoreTestCase (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) |
| { |
| de::Random rnd(0xabcdef); |
| |
| m_verifier->verifyInteger(m_testCtx, m_testTargetName, m_initialValue); |
| expectError(GL_NO_ERROR); |
| |
| const int numIterations = 120; |
| for (int i = 0; i < numIterations; ++i) |
| { |
| const int referenceValue = rnd.getInt(0, 64000); |
| |
| 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; |
| int m_initialValue; |
| }; |
| |
| 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]; |
| |
| 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, GL_MIN, GL_MAX |
| }; |
| |
| 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 TransformFeedbackBindingTestCase : public BindingTest |
| { |
| public: |
| TransformFeedbackBindingTestCase (Context& context, QueryType type, const char* name) |
| : BindingTest(context, name, "GL_TRANSFORM_FEEDBACK_BINDING", type) |
| { |
| } |
| |
| void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const |
| { |
| static const char* transformFeedbackTestVertSource = |
| "#version 300 es\n" |
| "void main (void)\n" |
| "{\n" |
| " gl_Position = vec4(0.0);\n" |
| "}\n\0"; |
| static const char* transformFeedbackTestFragSource = |
| "#version 300 es\n" |
| "layout(location = 0) out mediump vec4 fragColor;" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = vec4(0.0);\n" |
| "}\n\0"; |
| |
| GLuint shaderVert; |
| GLuint shaderFrag; |
| GLuint shaderProg; |
| GLuint transformfeedback = 0; |
| GLuint feedbackBufferId = 0; |
| |
| { |
| const tcu::ScopedLogSection section(gl.getLog(), "Initial", "Initial"); |
| verifyStateInteger(result, gl, GL_TRANSFORM_FEEDBACK_BINDING, 0, m_type); |
| } |
| |
| gl.glGenTransformFeedbacks(1, &transformfeedback); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenTransformFeedbacks"); |
| |
| { |
| const tcu::ScopedLogSection section(gl.getLog(), "VertexShader", "Vertex Shader"); |
| |
| GLint compileStatus = -1; |
| |
| shaderVert = gl.glCreateShader(GL_VERTEX_SHADER); |
| gl.glShaderSource(shaderVert, 1, &transformFeedbackTestVertSource, 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"); |
| |
| GLint compileStatus = -1; |
| |
| shaderFrag = gl.glCreateShader(GL_FRAGMENT_SHADER); |
| gl.glShaderSource(shaderFrag, 1, &transformFeedbackTestFragSource, 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"); |
| |
| const char* transform_feedback_outputs = "gl_Position"; |
| GLint linkStatus = -1; |
| |
| shaderProg = gl.glCreateProgram(); |
| gl.glAttachShader(shaderProg, shaderVert); |
| gl.glAttachShader(shaderProg, shaderFrag); |
| gl.glTransformFeedbackVaryings(shaderProg, 1, &transform_feedback_outputs, GL_INTERLEAVED_ATTRIBS); |
| 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.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformfeedback); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glBindTransformFeedback"); |
| |
| gl.glGenBuffers(1, &feedbackBufferId); |
| gl.glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, feedbackBufferId); |
| gl.glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_DYNAMIC_READ); |
| gl.glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, feedbackBufferId); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "bind buffers"); |
| |
| gl.glUseProgram(shaderProg); |
| |
| verifyStateInteger(result, gl, GL_TRANSFORM_FEEDBACK_BINDING, transformfeedback, m_type); |
| |
| gl.glUseProgram(0); |
| gl.glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); |
| gl.glDeleteTransformFeedbacks(1, &transformfeedback); |
| |
| verifyStateInteger(result, gl, GL_TRANSFORM_FEEDBACK_BINDING, 0, m_type); |
| |
| gl.glDeleteBuffers(1, &feedbackBufferId); |
| gl.glDeleteShader(shaderVert); |
| gl.glDeleteShader(shaderFrag); |
| gl.glDeleteProgram(shaderProg); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteProgram"); |
| } |
| }; |
| |
| 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 = |
| "#version 300 es\n" |
| "void main (void)\n" |
| "{\n" |
| " gl_Position = vec4(0.0);\n" |
| "}\n\0"; |
| static const char* testFragSource = |
| "#version 300 es\n" |
| "layout(location = 0) out mediump vec4 fragColor;" |
| "void main (void)\n" |
| "{\n" |
| " fragColor = vec4(0.0);\n" |
| "}\n\0"; |
| |
| GLuint shaderVert; |
| GLuint shaderFrag; |
| GLuint shaderProg; |
| |
| { |
| 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"); |
| |
| GLint compileStatus = -1; |
| |
| 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"); |
| |
| GLint compileStatus = -1; |
| |
| 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"); |
| |
| GLint linkStatus = -1; |
| |
| 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 VertexArrayBindingTestCase : public BindingTest |
| { |
| public: |
| VertexArrayBindingTestCase (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_VERTEX_ARRAY_BINDING, 0, m_type); |
| |
| GLuint vertexArrayObject = 0; |
| gl.glGenVertexArrays(1, &vertexArrayObject); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenVertexArrays"); |
| |
| gl.glBindVertexArray(vertexArrayObject); |
| verifyStateInteger(result, gl, GL_VERTEX_ARRAY_BINDING, vertexArrayObject, m_type); |
| |
| gl.glDeleteVertexArrays(1, &vertexArrayObject); |
| verifyStateInteger(result, gl, GL_VERTEX_ARRAY_BINDING, 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 ElementArrayBufferBindingTestCase : public BindingTest |
| { |
| public: |
| ElementArrayBufferBindingTestCase (Context& context, QueryType type, const char* name) |
| : BindingTest(context, name, "GL_ELEMENT_ARRAY_BUFFER_BINDING", type) |
| { |
| } |
| |
| void test (glu::CallLogWrapper& gl, tcu::ResultCollector& result) const |
| { |
| // Test with default VAO |
| { |
| const tcu::ScopedLogSection section(gl.getLog(), "DefaultVAO", "Test with default VAO"); |
| |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, m_type); |
| |
| GLuint bufferObject = 0; |
| gl.glGenBuffers(1, &bufferObject); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenBuffers"); |
| |
| gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObject); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, bufferObject, m_type); |
| |
| gl.glDeleteBuffers(1, &bufferObject); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, m_type); |
| } |
| |
| // Test with multiple VAOs |
| { |
| const tcu::ScopedLogSection section(gl.getLog(), "WithVAO", "Test with VAO"); |
| |
| GLuint vaos[2] = {0}; |
| GLuint buffers[2] = {0}; |
| |
| gl.glGenVertexArrays(2, vaos); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenVertexArrays"); |
| |
| gl.glGenBuffers(2, buffers); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenBuffers"); |
| |
| // initial |
| gl.glBindVertexArray(vaos[0]); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, m_type); |
| |
| // after setting |
| gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[0]); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, buffers[0], m_type); |
| |
| // initial of vao 2 |
| gl.glBindVertexArray(vaos[1]); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, m_type); |
| |
| // after setting to 2 |
| gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, buffers[1], m_type); |
| |
| // vao 1 still has buffer 1 bound? |
| gl.glBindVertexArray(vaos[0]); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, buffers[0], m_type); |
| |
| // deleting clears from bound vaos ... |
| gl.glDeleteBuffers(2, buffers); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, m_type); |
| |
| // ... but does not from non-bound vaos? |
| gl.glBindVertexArray(vaos[1]); |
| verifyStateInteger(result, gl, GL_ELEMENT_ARRAY_BUFFER_BINDING, buffers[1], m_type); |
| |
| gl.glDeleteVertexArrays(2, vaos); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteVertexArrays"); |
| } |
| } |
| }; |
| |
| 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); // mask should not affect the 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 SamplerObjectBindingTestCase : public BindingTest |
| { |
| public: |
| SamplerObjectBindingTestCase (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_SAMPLER_BINDING, 0, m_type); |
| |
| { |
| const tcu::ScopedLogSection section(gl.getLog(), "SingleUnit", "Single unit"); |
| |
| GLuint sampler = 0; |
| gl.glGenSamplers(1, &sampler); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenSamplers"); |
| |
| gl.glBindSampler(0, sampler); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glBindSampler"); |
| |
| verifyStateInteger(result, gl, GL_SAMPLER_BINDING, sampler, m_type); |
| |
| gl.glDeleteSamplers(1, &sampler); |
| verifyStateInteger(result, gl, GL_SAMPLER_BINDING, 0, m_type); |
| } |
| |
| { |
| const tcu::ScopedLogSection section(gl.getLog(), "MultipleUnits", "Multiple units"); |
| |
| GLuint samplerA = 0; |
| GLuint samplerB = 0; |
| gl.glGenSamplers(1, &samplerA); |
| gl.glGenSamplers(1, &samplerB); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glGenSamplers"); |
| |
| gl.glBindSampler(1, samplerA); |
| gl.glBindSampler(2, samplerB); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glBindSampler"); |
| |
| verifyStateInteger(result, gl, GL_SAMPLER_BINDING, 0, m_type); |
| |
| gl.glActiveTexture(GL_TEXTURE1); |
| verifyStateInteger(result, gl, GL_SAMPLER_BINDING, samplerA, m_type); |
| |
| gl.glActiveTexture(GL_TEXTURE2); |
| verifyStateInteger(result, gl, GL_SAMPLER_BINDING, samplerB, m_type); |
| |
| gl.glDeleteSamplers(1, &samplerB); |
| gl.glDeleteSamplers(1, &samplerA); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteSamplers"); |
| } |
| } |
| }; |
| |
| 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_DRAW_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_READ_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(), "bind GL_FRAMEBUFFER"); |
| |
| verifyStateInteger(result, gl, GL_DRAW_FRAMEBUFFER_BINDING, framebufferId, m_type); |
| verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, framebufferId, m_type); |
| verifyStateInteger(result, gl, GL_READ_FRAMEBUFFER_BINDING, framebufferId, m_type); |
| |
| gl.glBindFramebuffer(GL_FRAMEBUFFER, 0); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "unbind GL_FRAMEBUFFER"); |
| |
| verifyStateInteger(result, gl, GL_DRAW_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_READ_FRAMEBUFFER_BINDING, 0, m_type); |
| |
| gl.glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferId); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "bind GL_READ_FRAMEBUFFER"); |
| |
| verifyStateInteger(result, gl, GL_DRAW_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_READ_FRAMEBUFFER_BINDING, framebufferId, m_type); |
| |
| gl.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferId); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "bind GL_DRAW_FRAMEBUFFER"); |
| |
| verifyStateInteger(result, gl, GL_DRAW_FRAMEBUFFER_BINDING, framebufferId, m_type); |
| verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, framebufferId, m_type); |
| verifyStateInteger(result, gl, GL_READ_FRAMEBUFFER_BINDING, framebufferId, m_type); |
| |
| gl.glDeleteFramebuffers(1, &framebufferId); |
| GLS_COLLECT_GL_ERROR(result, gl.glGetError(), "glDeleteFramebuffers"); |
| |
| verifyStateInteger(result, gl, GL_DRAW_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_FRAMEBUFFER_BINDING, 0, m_type); |
| verifyStateInteger(result, gl, GL_READ_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_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, |
| GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_UNSIGNED_SHORT_5_6_5, |
| GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, |
| GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT_10F_11F_11F_REV |
| }; |
| const GLint defaultColorFormats[] = |
| { |
| GL_RGBA, GL_RGBA_INTEGER, GL_RGB, GL_RGB_INTEGER, |
| GL_RG, GL_RG_INTEGER, GL_RED, GL_RED_INTEGER |
| }; |
| |
| 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); |
| } |
| |
| 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 ReadBufferCase : public ApiCase |
| { |
| public: |
| ReadBufferCase (Context& context, StateVerifier* verifier, const char* name, const char* description) |
| : ApiCase (context, name, description) |
| , m_verifier (verifier) |
| { |
| } |
| |
| void test (void) |
| { |
| const GLint validInitialValues[] = {GL_BACK, GL_NONE}; |
| m_verifier->verifyIntegerAnyOf(m_testCtx, GL_READ_BUFFER, validInitialValues, DE_LENGTH_OF_ARRAY(validInitialValues)); |
| expectError(GL_NO_ERROR); |
| |
| glReadBuffer(GL_NONE); |
| m_verifier->verifyInteger(m_testCtx, GL_READ_BUFFER, GL_NONE); |
| expectError(GL_NO_ERROR); |
| |
| glReadBuffer(GL_BACK); |
| m_verifier->verifyInteger(m_testCtx, GL_READ_BUFFER, GL_BACK); |
| expectError(GL_NO_ERROR); |
| |
| // test GL_READ_BUFFER with framebuffers |
| |
| GLuint framebufferId = 0; |
| glGenFramebuffers(1, &framebufferId); |
| expectError(GL_NO_ERROR); |
| |
| GLuint renderbuffer_id = 0; |
| glGenRenderbuffers(1, &renderbuffer_id); |
| expectError(GL_NO_ERROR); |
| |
| glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_id); |
| expectError(GL_NO_ERROR); |
| |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 128, 128); |
| expectError(GL_NO_ERROR); |
| |
| glBindFramebuffer(GL_READ_FRAMEBUFFER, framebufferId); |
| expectError(GL_NO_ERROR); |
| |
| glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer_id); |
| expectError(GL_NO_ERROR); |
| |
| m_verifier->verifyInteger(m_testCtx, GL_READ_BUFFER, GL_COLOR_ATTACHMENT0); |
| |
| glDeleteFramebuffers(1, &framebufferId); |
| glDeleteRenderbuffers(1, &renderbuffer_id); |
| expectError(GL_NO_ERROR); |
| |
| m_verifier->verifyInteger(m_testCtx, GL_READ_BUFFER, GL_BACK); |
| expectError(GL_NO_ERROR); |
| } |
| private: |
| StateVerifier* m_verifier; |
| }; |
| |
| class DrawBufferCase : public ApiCase |
| { |
| public: |
| DrawBufferCase (Context& context, StateVerifier* verifier, const char* name, const char* description) |
| : ApiCase (context, name, description) |
| , m_verifier (verifier) |
| { |
| } |
| |
| void test (void) |
| { |
| const GLint validInitialValues[] = {GL_BACK, GL_NONE}; |
| m_verifier->verifyIntegerAnyOf(m_testCtx, GL_DRAW_BUFFER0, validInitialValues, DE_LENGTH_OF_ARRAY(validInitialValues)); |
| expectError(GL_NO_ERROR); |
| |
| GLenum bufs = GL_NONE; |
| glDrawBuffers(1, &bufs); |
| m_verifier->verifyInteger(m_testCtx, GL_DRAW_BUFFER0, GL_NONE); |
| expectError(GL_NO_ERROR); |
| |
| bufs = GL_BACK; |
| glDrawBuffers(1, &bufs); |
| m_verifier->verifyInteger(m_testCtx, GL_DRAW_BUFFER0, GL_BACK); |
| expectError(GL_NO_ERROR); |
| |
| // test GL_DRAW_BUFFER with framebuffers |
| |
| GLuint framebufferId = 0; |
| glGenFramebuffers(1, &framebufferId); |
| expectError(GL_NO_ERROR); |
| |
| GLuint renderbuffer_ids[2] = {0}; |
| glGenRenderbuffers(2, renderbuffer_ids); |
| expectError(GL_NO_ERROR); |
| |
| glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_ids[0]); |
| expectError(GL_NO_ERROR); |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 128, 128); |
| expectError(GL_NO_ERROR); |
| |
| glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_ids[1]); |
| expectError(GL_NO_ERROR); |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 128, 128); |
| expectError(GL_NO_ERROR); |
| |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, framebufferId); |
| expectError(GL_NO_ERROR); |
| |
| glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer_ids[0]); |
| expectError(GL_NO_ERROR); |
| glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, renderbuffer_ids[1]); |
| expectError(GL_NO_ERROR); |
| |
| // only the initial state the draw buffer for fragment color zero is defined |
| m_verifier->verifyInteger(m_testCtx, GL_DRAW_BUFFER0, GL_COLOR_ATTACHMENT0); |
| |
| GLenum bufTargets[2] = {GL_NONE, GL_COLOR_ATTACHMENT1}; |
| glDrawBuffers(2, bufTargets); |
| m_verifier->verifyInteger(m_testCtx, GL_DRAW_BUFFER0, GL_NONE); |
| m_verifier->verifyInteger(m_testCtx, GL_DRAW_BUFFER1, GL_COLOR_ATTACHMENT1); |
| |
| glDeleteFramebuffers(1, &framebufferId); |
| glDeleteRenderbuffers(2, renderbuffer_ids); |
| expectError(GL_NO_ERROR); |
| |
| m_verifier->verifyInteger(m_testCtx, GL_DRAW_BUFFER0, GL_BACK); |
| 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_INTEGER64: return "_getinteger64"; |
| 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; \ |
| } |
|