| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2015-2016 The Khronos Group Inc. |
| * |
| * 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 |
| */ /*-------------------------------------------------------------------*/ |
| |
| /** |
| */ /*! |
| * \file gl4cDirectStateAccessBuffersTests.cpp |
| * \brief Conformance tests for the Direct State Access feature functionality (Buffer access part). |
| */ /*-----------------------------------------------------------------------------------------------------------*/ |
| |
| /* Includes. */ |
| #include "gl4cDirectStateAccessTests.hpp" |
| |
| #include "deSharedPtr.hpp" |
| |
| #include "gluContextInfo.hpp" |
| #include "gluDefs.hpp" |
| #include "gluPixelTransfer.hpp" |
| #include "gluStrUtil.hpp" |
| |
| #include "tcuFuzzyImageCompare.hpp" |
| #include "tcuImageCompare.hpp" |
| #include "tcuRenderTarget.hpp" |
| #include "tcuSurface.hpp" |
| #include "tcuTestLog.hpp" |
| |
| #include "glw.h" |
| #include "glwFunctions.hpp" |
| |
| #include <algorithm> |
| #include <climits> |
| #include <set> |
| #include <sstream> |
| #include <stack> |
| #include <string> |
| |
| namespace gl4cts |
| { |
| namespace DirectStateAccess |
| { |
| namespace Buffers |
| { |
| /******************************** Creation Test Implementation ********************************/ |
| |
| /** @brief Creation Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| CreationTest::CreationTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_creation", "Buffer Objects Creation Test") |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Creation Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult CreationTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* Buffers' objects */ |
| static const glw::GLuint buffers_count = 2; |
| |
| glw::GLuint buffers_legacy[buffers_count] = {}; |
| glw::GLuint buffers_dsa[buffers_count] = {}; |
| |
| try |
| { |
| /* Check legacy state creation. */ |
| gl.genBuffers(buffers_count, buffers_legacy); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed"); |
| |
| for (glw::GLuint i = 0; i < buffers_count; ++i) |
| { |
| if (gl.isBuffer(buffers_legacy[i])) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "GenBuffers has created default objects, but it should create only a names." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| |
| /* Check direct state creation. */ |
| gl.createBuffers(buffers_count, buffers_dsa); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers have failed"); |
| |
| for (glw::GLuint i = 0; i < buffers_count; ++i) |
| { |
| if (!gl.isBuffer(buffers_dsa[i])) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "CreateBuffers has not created default objects." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Cleanup. */ |
| for (glw::GLuint i = 0; i < buffers_count; ++i) |
| { |
| if (buffers_legacy[i]) |
| { |
| gl.deleteBuffers(1, &buffers_legacy[i]); |
| |
| buffers_legacy[i] = 0; |
| } |
| |
| if (buffers_dsa[i]) |
| { |
| gl.deleteBuffers(1, &buffers_dsa[i]); |
| |
| buffers_dsa[i] = 0; |
| } |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /******************************** Data Test Implementation ********************************/ |
| |
| /** @brief Data Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| DataTest::DataTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_data", "Buffer Objects Data Test") |
| , m_pNamedBufferData(DE_NULL) |
| , m_pNamedBufferSubData(DE_NULL) |
| , m_pNamedBufferStorage(DE_NULL) |
| , m_pCopyNamedBufferSubData(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Data Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult DataTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATA)gl.namedBufferSubData; |
| m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage; |
| m_pCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATA)gl.copyNamedBufferSubData; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pNamedBufferSubData) || |
| (DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pCopyNamedBufferSubData)) |
| { |
| throw 0; |
| } |
| |
| /* BufferData tests */ |
| static const glw::GLenum hints[] = { GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, |
| GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, |
| GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, GL_DYNAMIC_COPY }; |
| static const glw::GLuint hints_count = sizeof(hints) / sizeof(hints[0]); |
| |
| for (glw::GLuint i = 0; i < hints_count; ++i) |
| { |
| is_ok &= TestCase(&DataTest::UploadUsingNamedBufferData, hints[i]); |
| is_ok &= TestCase(&DataTest::UploadUsingNamedBufferSubData, hints[i]); |
| is_ok &= TestCase(&DataTest::UploadUsingCopyNamedBufferSubData, hints[i]); |
| } |
| |
| /* BufferStorage Tests */ |
| static const glw::GLenum bits[] = { GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, |
| GL_MAP_READ_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT, |
| GL_MAP_READ_BIT | GL_CLIENT_STORAGE_BIT }; |
| static const glw::GLuint bits_count = sizeof(bits) / sizeof(bits[0]); |
| |
| for (glw::GLuint i = 0; i < bits_count; ++i) |
| { |
| is_ok &= TestCase(&DataTest::UploadUsingNamedBufferStorage, bits[i]); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /** @brief Data uploading test case function. |
| * |
| * @param [in] UploadDataFunction Function pointer to the tested data uploading function. |
| * @param [in] parameter Storage Parameter to be used with the function (function dependent). |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| bool DataTest::TestCase(void (DataTest::*UploadDataFunction)(glw::GLuint, glw::GLenum), glw::GLenum parameter) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| glw::GLuint buffer = 0; |
| bool is_ok = true; |
| bool is_error = false; |
| |
| try |
| { |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| (this->*UploadDataFunction)(buffer, parameter); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed."); |
| |
| glw::GLuint* data = (glw::GLuint*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed."); |
| |
| is_ok = compare(data, s_reference, s_reference_count); |
| |
| if (!is_ok) |
| { |
| LogFail(UploadDataFunction, parameter, data, s_reference, s_reference_count); |
| } |
| |
| gl.unmapBuffer(GL_ARRAY_BUFFER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed."); |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| |
| LogError(UploadDataFunction, parameter); |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed."); |
| } |
| |
| if (is_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief NamedBufferData data upload function. |
| * |
| * @param [in] id Buffer id to be uploaded. |
| * @param [in] parameter Storage Parameter to be used with the function, one of: |
| * - GL_STREAM_DRAW, |
| * - GL_STREAM_READ, |
| * - GL_STREAM_COPY, |
| * - GL_STATIC_DRAW, |
| * - GL_STATIC_READ, |
| * - GL_STATIC_COPY, |
| * - GL_DYNAMIC_DRAW, |
| * - GL_DYNAMIC_READ and |
| * - GL_DYNAMIC_COPY. |
| */ |
| void DataTest::UploadUsingNamedBufferData(glw::GLuint id, glw::GLenum parameter) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_pNamedBufferData(id, s_reference_size, s_reference, parameter); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| } |
| |
| /** @brief NamedBufferSubData data upload function. |
| * |
| * @param [in] id Buffer id to be uploaded. |
| * @param [in] parameter Storage parameter to be used with the NamedBufferData for |
| * the storage allocation (before call to NamedBufferSubData), one of: |
| * - GL_STREAM_DRAW, |
| * - GL_STREAM_READ, |
| * - GL_STREAM_COPY, |
| * - GL_STATIC_DRAW, |
| * - GL_STATIC_READ, |
| * - GL_STATIC_COPY, |
| * - GL_DYNAMIC_DRAW, |
| * - GL_DYNAMIC_READ and |
| * - GL_DYNAMIC_COPY. |
| */ |
| void DataTest::UploadUsingNamedBufferSubData(glw::GLuint id, glw::GLenum parameter) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_pNamedBufferData(id, s_reference_size, DE_NULL, parameter); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| m_pNamedBufferSubData(id, 0, s_reference_size, s_reference); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferSubData failed."); |
| } |
| |
| /** @brief NamedBufferStorage data upload function. |
| * |
| * @param [in] id Buffer id to be uploaded. |
| * @param [in] parameter Storage Parameter to be used with the function, one of: |
| * - GL_MAP_READ_BIT | GL_DYNAMIC_STORAGE_BIT, |
| * - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, |
| * - GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, |
| * - GL_MAP_READ_BIT | GL_MAP_COHERENT_BIT, |
| * - GL_MAP_READ_BIT | GL_CLIENT_STORAGE_BIT |
| */ |
| void DataTest::UploadUsingNamedBufferStorage(glw::GLuint id, glw::GLenum parameter) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_pNamedBufferStorage(id, s_reference_size, s_reference, parameter); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage failed."); |
| } |
| |
| /** @brief CopyNamedBufferSubData data upload function (uses auxiliary buffer object). |
| * |
| * @param [in] id Buffer id to be uploaded. |
| * @param [in] parameter Storage parameter to be used with the NamedBufferData for |
| * the auxiliary buffer object storage allocation |
| * (before call to CopyNamedBufferSubData), one of: |
| * - GL_STREAM_DRAW, |
| * - GL_STREAM_READ, |
| * - GL_STREAM_COPY, |
| * - GL_STATIC_DRAW, |
| * - GL_STATIC_READ, |
| * - GL_STATIC_COPY, |
| * - GL_DYNAMIC_DRAW, |
| * - GL_DYNAMIC_READ and |
| * - GL_DYNAMIC_COPY. |
| */ |
| void DataTest::UploadUsingCopyNamedBufferSubData(glw::GLuint id, glw::GLenum parameter) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_pNamedBufferData(id, s_reference_size, DE_NULL, parameter); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| glw::GLuint auxiliary_buffer = 0; |
| bool auxiliary_buffer_is_ok = true; |
| |
| try |
| { |
| gl.genBuffers(1, &auxiliary_buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers failed."); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, auxiliary_buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed."); |
| |
| gl.bufferData(GL_ARRAY_BUFFER, s_reference_size, s_reference, parameter); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData failed."); |
| |
| m_pCopyNamedBufferSubData(auxiliary_buffer, id, 0, 0, s_reference_size); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCopyNamedBufferSubData failed."); |
| } |
| catch (...) |
| { |
| auxiliary_buffer_is_ok = false; |
| } |
| |
| if (auxiliary_buffer) |
| { |
| gl.deleteBuffers(1, &auxiliary_buffer); |
| } |
| |
| if (!auxiliary_buffer_is_ok) |
| { |
| throw 0; |
| } |
| } |
| |
| /** @brief Compare two unsigned integer arrays. |
| * |
| * @param [in] data Data to be compared. |
| * @param [in] reference Reference data to be compared to. |
| * @param [in] count Number of elements to be compared. |
| * |
| * @return True if count of data the elements are equal to reference counterparts, false otherwise. |
| */ |
| bool DataTest::compare(const glw::GLuint* data, const glw::GLuint* reference, const glw::GLsizei count) |
| { |
| for (glw::GLsizei i = 0; i < count; ++i) |
| { |
| if (data[i] != reference[i]) |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** @brief Prepare error message and log it. |
| * |
| * @param [in] UploadDataFunction Upload function pointer which have failed, one of: |
| * - DataTest::UploadUsingNamedBufferData, |
| * - DataTest::UploadUsingNamedBufferSubData |
| * - DataTest::UploadUsingNamedBufferStorage and |
| * - DataTest::UploadUsingCopyNamedBufferSubData. |
| * @param [in] parameter Parameter which was passed to function. |
| * @param [in] data Data which was downloaded. |
| * @param [in] reference Reference data. |
| * @param [in] count Number of elements compared. |
| */ |
| void DataTest::LogFail(void (DataTest::*UploadDataFunction)(glw::GLuint, glw::GLenum), glw::GLenum parameter, |
| const glw::GLuint* data, const glw::GLuint* reference, const glw::GLsizei count) |
| { |
| std::string the_log = "The test of "; |
| |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferData) |
| { |
| the_log.append("glNamedBufferData"); |
| } |
| else |
| { |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferSubData) |
| { |
| the_log.append("glNamedBufferSubData"); |
| } |
| else |
| { |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage) |
| { |
| the_log.append("glNamedBufferStorage"); |
| } |
| else |
| { |
| if (UploadDataFunction == &DataTest::UploadUsingCopyNamedBufferSubData) |
| { |
| the_log.append("glCopyNamedBufferSubData"); |
| } |
| else |
| { |
| the_log.append("uknown upload function"); |
| } |
| } |
| } |
| } |
| |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage) |
| { |
| the_log.append(" called with usage parameter "); |
| |
| std::stringstream bitfield_string_stream; |
| bitfield_string_stream << glu::getBufferMapFlagsStr(parameter); |
| the_log.append(bitfield_string_stream.str()); |
| } |
| else |
| { |
| the_log.append(" called with usage parameter "); |
| the_log.append(glu::getUsageName(parameter)); |
| } |
| the_log.append(". Buffer data is equal to ["); |
| |
| for (glw::GLsizei i = 0; i < count; ++i) |
| { |
| std::stringstream number; |
| |
| number << data[i]; |
| |
| the_log.append(number.str()); |
| |
| if (i != count - 1) |
| { |
| the_log.append(", "); |
| } |
| } |
| |
| the_log.append("], but ["); |
| |
| for (glw::GLsizei i = 0; i < count; ++i) |
| { |
| std::stringstream number; |
| |
| number << reference[i]; |
| |
| the_log.append(number.str()); |
| |
| if (i != count - 1) |
| { |
| the_log.append(", "); |
| } |
| } |
| |
| the_log.append("] was expected."); |
| |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage; |
| } |
| |
| void DataTest::LogError(void (DataTest::*UploadDataFunction)(glw::GLuint, glw::GLenum), glw::GLenum parameter) |
| { |
| std::string the_log = "Unexpected error occurred during the test of "; |
| |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferData) |
| { |
| the_log.append("glNamedBufferData"); |
| } |
| else |
| { |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferSubData) |
| { |
| the_log.append("glNamedBufferSubData"); |
| } |
| else |
| { |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage) |
| { |
| the_log.append("glNamedBufferStorage"); |
| } |
| else |
| { |
| if (UploadDataFunction == &DataTest::UploadUsingCopyNamedBufferSubData) |
| { |
| the_log.append("glCopyNamedBufferSubData"); |
| } |
| else |
| { |
| the_log.append("uknown upload function"); |
| } |
| } |
| } |
| } |
| |
| if (UploadDataFunction == &DataTest::UploadUsingNamedBufferStorage) |
| { |
| the_log.append(" called with usage parameter "); |
| |
| std::stringstream bitfield_string_stream; |
| bitfield_string_stream << glu::getBufferMapFlagsStr(parameter); |
| the_log.append(bitfield_string_stream.str()); |
| } |
| else |
| { |
| the_log.append(" called with usage parameter "); |
| the_log.append(glu::getUsageName(parameter)); |
| } |
| the_log.append("."); |
| |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage; |
| } |
| |
| const glw::GLuint DataTest::s_reference[] = { |
| 0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 |
| }; //!< Reference data. |
| const glw::GLsizei DataTest::s_reference_size = sizeof(s_reference); //!< Size of the reference data. |
| const glw::GLsizei DataTest::s_reference_count = |
| s_reference_size / sizeof(s_reference[0]); //!< NUmber of elements of the reference data. |
| |
| /******************************** Clear Test Implementation ********************************/ |
| |
| /** @brief Data Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| ClearTest::ClearTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_clear", "Buffer Objects Clear Test") |
| , m_pNamedBufferData(DE_NULL) |
| , m_pClearNamedBufferData(DE_NULL) |
| , m_pClearNamedBufferSubData(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief ClearNamedBufferData wrapper implementation. |
| * |
| * @note USE_SUB_DATA == false, so ClearNamedBufferData will be used. |
| * |
| * @param [in] buffer ID of the buffer to be cleared. |
| * @param [in] internalformat GL internal format for clearing, one of the listed in test class description. |
| * @param [in] size Size of the data. |
| * @param [in] format GL Format of the data. |
| * @param [in] type GL Type of the data element. |
| * @param [in] data Data to be cleared with. |
| */ |
| template <> |
| void ClearTest::ClearNamedBuffer<false>(glw::GLuint buffer, glw::GLenum internalformat, glw::GLsizei size, |
| glw::GLenum format, glw::GLenum type, glw::GLvoid* data) |
| { |
| (void)size; |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_pClearNamedBufferData(buffer, internalformat, format, type, data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearNamedBufferData failed."); |
| } |
| |
| /** @brief ClearNamedBufferSubData wrapper implementation. |
| * |
| * @note USE_SUB_DATA == true, so ClearNamedBufferSubData will be used. |
| * |
| * @param [in] buffer ID of the buffer to be cleared. |
| * @param [in] internalformat GL internal format for clearing, one of the listed in test class description. |
| * @param [in] size Size of the data. |
| * @param [in] format GL Format of the data. |
| * @param [in] type GL Type of the data element. |
| * @param [in] data Data to be cleared with. |
| */ |
| template <> |
| void ClearTest::ClearNamedBuffer<true>(glw::GLuint buffer, glw::GLenum internalformat, glw::GLsizei size, |
| glw::GLenum format, glw::GLenum type, glw::GLvoid* data) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| m_pClearNamedBufferSubData(buffer, internalformat, 0, size, format, type, data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glClearNamedBufferData failed."); |
| } |
| |
| /** @brief Compare two arrays with elements of type T == GLfloat (specialized). |
| * |
| * @param [in] data Data to be compared. |
| * @param [in] reference Reference data to be compared to. |
| * @param [in] count Number of elements to be compared. |
| * |
| * @return True if count of data the elements are equal to reference counterparts, false otherwise. |
| */ |
| template <> |
| bool ClearTest::Compare<glw::GLfloat>(const glw::GLfloat* data, const glw::GLfloat* reference, const glw::GLsizei count) |
| { |
| for (glw::GLsizei i = 0; i < count; ++i) |
| { |
| if (de::abs(data[i] - reference[i]) > 0.00001 /* Precision. */) |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** @brief Compare two arrays with elements of type T. |
| * |
| * @tparam T Type of data to be compared (anything which is not GLfloat. |
| * Floating point numbers have another specialized implementation, |
| * which accounts the precision issues. |
| * |
| * @param [in] data Data to be compared. |
| * @param [in] reference Reference data to be compared to. |
| * @param [in] count Number of elements to be compared. |
| * |
| * @return True if count of data the elements are equal to reference counterparts, false otherwise. |
| */ |
| template <typename T> |
| bool ClearTest::Compare(const T* data, const T* reference, const glw::GLsizei count) |
| { |
| for (glw::GLsizei i = 0; i < count; ++i) |
| { |
| if (data[i] != reference[i]) |
| { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** @brief Prepare error message and log it. |
| * |
| * @tparam T Type of data to which was tested. |
| * |
| * @param [in] internalformat Internal format used for clearing, one of the listed in test class description. |
| * @param [in] data Data which was used for clear test. |
| * @param [in] reference Reference data. |
| * @param [in] count Number of elements to be compared. |
| */ |
| template <typename T> |
| void ClearTest::LogFail(bool use_sub_data, glw::GLenum internalformat, const T* data, const T* reference, |
| const glw::GLsizei count) |
| { |
| (void)internalformat; |
| std::string the_log = "The test of "; |
| |
| if (use_sub_data) |
| { |
| the_log.append("ClearNamedBufferSubData has failed for internalformat "); |
| } |
| else |
| { |
| the_log.append("ClearNamedBufferData has failed for internalformat "); |
| } |
| |
| //the_log.append(glu::getPixelFormatName(internalformat)); |
| the_log.append(". Cleared buffer data is equal to ["); |
| |
| for (glw::GLsizei i = 0; i < count; ++i) |
| { |
| std::stringstream number; |
| |
| number << data[i]; |
| |
| the_log.append(number.str()); |
| |
| if (i != count - 1) |
| { |
| the_log.append(", "); |
| } |
| } |
| |
| the_log.append("], but ["); |
| |
| for (glw::GLsizei i = 0; i < count; ++i) |
| { |
| std::stringstream number; |
| |
| number << reference[i]; |
| |
| the_log.append(number.str()); |
| |
| if (i != count - 1) |
| { |
| the_log.append(", "); |
| } |
| } |
| |
| the_log.append("] was expected."); |
| |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage; |
| } |
| |
| void ClearTest::LogError(bool use_sub_data, glw::GLenum internalformat) |
| { |
| (void)internalformat; |
| std::string the_log = "Unexpected error occurred during Test of "; |
| |
| if (use_sub_data) |
| { |
| the_log.append("ClearNamedBufferSubData with internalformat "); |
| } |
| else |
| { |
| the_log.append("ClearNamedBufferData with internalformat "); |
| } |
| |
| //the_log.append(glu::getPixelFormatName(internalformat)); |
| |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << the_log << tcu::TestLog::EndMessage; |
| } |
| |
| /** @brief Run CLearing test case. |
| * |
| * @tparam T Type of data to which to be tested. |
| * @tparam USE_SUB_DATA If true ClearNamedBufferSubData will be used, ClearNamedBufferData otherwise. |
| * |
| * @param [in] internalformat Internal format used for clearing, one of the listed in test class description. |
| * @param [in] count Number of elements. |
| * @param [in] internalformat Data format to be used for clearing. |
| * @param [in] data Data to be used with clear test. |
| * |
| * @return True if test case succeeded, false otherwise. |
| */ |
| template <typename T, bool USE_SUB_DATA> |
| bool ClearTest::TestClearNamedBufferData(glw::GLenum internalformat, glw::GLsizei count, glw::GLenum format, |
| glw::GLenum type, T* data) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| glw::GLuint buffer = 0; |
| bool is_ok = true; |
| bool is_error = false; |
| |
| try |
| { |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferData(buffer, static_cast<glw::GLsizei>(count * sizeof(T)), NULL, GL_DYNAMIC_COPY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| ClearNamedBuffer<USE_SUB_DATA>(buffer, internalformat, static_cast<glw::GLsizei>(count * sizeof(T)), format, |
| type, data); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed."); |
| |
| T* _data = (T*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed."); |
| |
| is_ok = Compare<T>(_data, data, count); |
| |
| if (!is_ok) |
| { |
| /* Log. */ |
| LogFail<T>(USE_SUB_DATA, internalformat, _data, data, count); |
| } |
| |
| gl.unmapBuffer(GL_ARRAY_BUFFER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed."); |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| |
| LogError(USE_SUB_DATA, internalformat); |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed."); |
| } |
| |
| if (is_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Iterate Data Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult ClearTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATA)gl.clearNamedBufferData; |
| m_pClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATA)gl.clearNamedBufferSubData; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pClearNamedBufferData) || |
| (DE_NULL == m_pClearNamedBufferSubData)) |
| { |
| throw 0; |
| } |
| |
| { |
| /* unsigned byte norm component ClearNamedBufferData tests */ |
| glw::GLubyte reference[4] = { 5, 1, 2, 3 }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_R8, 1, GL_RED, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RG8, 2, GL_RG, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RGBA8, 4, GL_RGBA, GL_UNSIGNED_BYTE, reference); |
| |
| /* unsigned byte norm component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_R8, 1, GL_RED, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RG8, 2, GL_RG, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RGBA8, 4, GL_RGBA, GL_UNSIGNED_BYTE, reference); |
| |
| /* unsigned byte component ClearNamedBufferData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_R8UI, 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RG8UI, 2, GL_RG_INTEGER, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, false>(GL_RGBA8UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, reference); |
| |
| /* unsigned byte component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_R8UI, 1, GL_RED_INTEGER, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RG8UI, 2, GL_RG_INTEGER, GL_UNSIGNED_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLubyte, true>(GL_RGBA8UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, reference); |
| } |
| |
| { |
| /* signed byte component ClearNamedBufferData tests */ |
| glw::GLbyte reference[4] = { 5, 1, -2, 3 }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLbyte, false>(GL_R8I, 1, GL_RED_INTEGER, GL_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLbyte, false>(GL_RG8I, 2, GL_RG_INTEGER, GL_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLbyte, false>(GL_RGBA8I, 4, GL_RGBA_INTEGER, GL_BYTE, reference); |
| |
| /* signed byte component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLbyte, true>(GL_R8I, 1, GL_RED_INTEGER, GL_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLbyte, true>(GL_RG8I, 2, GL_RG_INTEGER, GL_BYTE, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLbyte, true>(GL_RGBA8I, 4, GL_RGBA_INTEGER, GL_BYTE, reference); |
| } |
| |
| { |
| /* unsigned short norm component ClearNamedBufferData tests */ |
| glw::GLushort reference[4] = { 5, 1, 2, 3 }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_R16, 1, GL_RED, GL_UNSIGNED_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_RG16, 2, GL_RG, GL_UNSIGNED_SHORT, reference); |
| is_ok &= |
| TestClearNamedBufferData<glw::GLushort, false>(GL_RGBA16, 4, GL_RGBA, GL_UNSIGNED_SHORT, reference); |
| |
| /* unsigned short norm component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_R16, 1, GL_RED, GL_UNSIGNED_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_RG16, 2, GL_RG, GL_UNSIGNED_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_RGBA16, 4, GL_RGBA, GL_UNSIGNED_SHORT, reference); |
| |
| /* unsigned short component ClearNamedBufferData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_R16UI, 1, GL_RED_INTEGER, GL_UNSIGNED_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLushort, false>(GL_RG16UI, 2, GL_RG_INTEGER, GL_UNSIGNED_SHORT, reference); |
| is_ok &= |
| TestClearNamedBufferData<glw::GLushort, false>(GL_RGBA16UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, reference); |
| |
| /* unsigned short component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_R16UI, 1, GL_RED_INTEGER, GL_UNSIGNED_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLushort, true>(GL_RG16UI, 2, GL_RG_INTEGER, GL_UNSIGNED_SHORT, reference); |
| is_ok &= |
| TestClearNamedBufferData<glw::GLushort, true>(GL_RGBA16UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, reference); |
| } |
| |
| { |
| /* signed short component ClearNamedBufferData tests */ |
| glw::GLshort reference[4] = { 5, 1, -2, 3 }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLshort, false>(GL_R16I, 1, GL_RED_INTEGER, GL_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLshort, false>(GL_RG16I, 2, GL_RG_INTEGER, GL_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLshort, false>(GL_RGBA16I, 4, GL_RGBA_INTEGER, GL_SHORT, reference); |
| |
| /* signed short component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLshort, true>(GL_R16I, 1, GL_RED_INTEGER, GL_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLshort, true>(GL_RG16I, 2, GL_RG_INTEGER, GL_SHORT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLshort, true>(GL_RGBA16I, 4, GL_RGBA_INTEGER, GL_SHORT, reference); |
| } |
| |
| { |
| /* unsigned int component ClearNamedBufferData tests */ |
| glw::GLuint reference[4] = { 5, 1, 2, 3 }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_R32UI, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_RG32UI, 2, GL_RG_INTEGER, GL_UNSIGNED_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_RGB32UI, 3, GL_RGB_INTEGER, GL_UNSIGNED_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLuint, false>(GL_RGBA32UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_INT, reference); |
| |
| /* unsigned int component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_R32UI, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_RG32UI, 2, GL_RG_INTEGER, GL_UNSIGNED_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_RGB32UI, 3, GL_RGB_INTEGER, GL_UNSIGNED_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLuint, true>(GL_RGBA32UI, 4, GL_RGBA_INTEGER, GL_UNSIGNED_INT, reference); |
| } |
| |
| { |
| /* signed int component ClearNamedBufferData tests */ |
| glw::GLint reference[4] = { 5, 1, -2, 3 }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_R32I, 1, GL_RED_INTEGER, GL_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_RG32I, 2, GL_RG_INTEGER, GL_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_RGB32I, 3, GL_RGB_INTEGER, GL_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLint, false>(GL_RGBA32I, 4, GL_RGBA_INTEGER, GL_INT, reference); |
| |
| /* signed int component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_R32I, 1, GL_RED_INTEGER, GL_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_RG32I, 2, GL_RG_INTEGER, GL_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_RGB32I, 3, GL_RGB_INTEGER, GL_INT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLint, true>(GL_RGBA32I, 4, GL_RGBA_INTEGER, GL_INT, reference); |
| } |
| |
| { |
| /* half float component ClearNamedBufferData tests */ |
| glw::GLhalf reference[4] = { 0x3C00 /* 1.0hf */, 0x0000 /* 0.0hf */, 0xC000 /* -2.0hf */, |
| 0x3555 /* 0.333333333hf */ }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLhalf, false>(GL_R16F, 1, GL_RED, GL_HALF_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLhalf, false>(GL_RG16F, 2, GL_RG, GL_HALF_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLhalf, false>(GL_RGBA16F, 4, GL_RGBA, GL_HALF_FLOAT, reference); |
| |
| /* half float component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLhalf, true>(GL_R16F, 1, GL_RED, GL_HALF_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLhalf, true>(GL_RG16F, 2, GL_RG, GL_HALF_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLhalf, true>(GL_RGBA16F, 4, GL_RGBA, GL_HALF_FLOAT, reference); |
| } |
| |
| { |
| /* float component ClearNamedBufferData tests */ |
| glw::GLfloat reference[4] = { 1.f, 0.f, -2.f, 0.3333333333f }; |
| |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_R32F, 1, GL_RED, GL_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_RG32F, 2, GL_RG, GL_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_RGB32F, 3, GL_RGB, GL_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, false>(GL_RGBA32F, 4, GL_RGBA, GL_FLOAT, reference); |
| |
| /* float component ClearNamedBufferSubData tests */ |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_R32F, 1, GL_RED, GL_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_RG32F, 2, GL_RG, GL_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_RGB32F, 3, GL_RGB, GL_FLOAT, reference); |
| is_ok &= TestClearNamedBufferData<glw::GLfloat, true>(GL_RGBA32F, 4, GL_RGBA, GL_FLOAT, reference); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /******************************** Map Read Only Test Implementation ********************************/ |
| |
| /** @brief Map Read Only Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| MapReadOnlyTest::MapReadOnlyTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_map_read_only", "Buffer Objects Map Read Only Test") |
| , m_pNamedBufferData(DE_NULL) |
| , m_pMapNamedBuffer(DE_NULL) |
| , m_pUnmapNamedBuffer(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Map Read Only Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult MapReadOnlyTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| glw::GLuint buffer = 0; |
| |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer; |
| m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pUnmapNamedBuffer)) |
| { |
| throw 0; |
| } |
| |
| /* Buffer creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Buffer's storage allocation and reference data upload. */ |
| m_pNamedBufferData(buffer, s_reference_size, s_reference, GL_DYNAMIC_COPY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| /* Mapping with new named buffer map function. */ |
| glw::GLuint* data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| if (DE_NULL == data) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "glMapNamedBuffer returned NULL pointer, but buffer's data was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| else |
| { |
| /* Comparison results with reference data. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| is_ok &= (data[i] == s_reference[i]); |
| } |
| |
| if (!is_ok) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glMapNamedBuffer returned pointer to data which is not identical to reference data." |
| << tcu::TestLog::EndMessage; |
| } |
| |
| /* Unmapping with new named buffer unmap function. */ |
| if (GL_TRUE != m_pUnmapNamedBuffer(buffer)) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = false; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| const glw::GLuint MapReadOnlyTest::s_reference[] = { 0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 }; |
| const glw::GLsizei MapReadOnlyTest::s_reference_size = sizeof(s_reference); |
| const glw::GLsizei MapReadOnlyTest::s_reference_count = s_reference_size / sizeof(s_reference[0]); |
| |
| /******************************** Map Read Write Test Implementation ********************************/ |
| |
| /** @brief Map Read Write Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| MapReadWriteTest::MapReadWriteTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_map_read_write", "Buffer Objects Map Read Write Test") |
| , m_pNamedBufferData(DE_NULL) |
| , m_pMapNamedBuffer(DE_NULL) |
| , m_pUnmapNamedBuffer(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Map Read Write Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult MapReadWriteTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| glw::GLuint buffer = 0; |
| |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer; |
| m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pUnmapNamedBuffer)) |
| { |
| throw 0; |
| } |
| |
| /* Buffer creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Buffer's storage allocation and reference data upload. */ |
| m_pNamedBufferData(buffer, s_reference_size, s_reference, GL_DYNAMIC_COPY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| /* Mapping with new named buffer map function. */ |
| glw::GLuint* data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_READ_WRITE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| if (DE_NULL == data) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "glMapNamedBuffer returned NULL pointer, but buffer's data was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| else |
| { |
| /* Comparison results with reference data. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| is_ok &= (data[i] == s_reference[i]); |
| } |
| |
| if (!is_ok) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glMapNamedBuffer returned pointer to data which is not identical to reference data." |
| << tcu::TestLog::EndMessage; |
| } |
| |
| /* Writting inverted reference data. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| data[i] = s_reference[s_reference_count - i - 1]; |
| } |
| |
| /* Unmapping with new named buffer unmap function. */ |
| if (GL_TRUE != m_pUnmapNamedBuffer(buffer)) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| data = DE_NULL; |
| |
| data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_READ_WRITE); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| if (DE_NULL == data) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glMapNamedBuffer returned NULL pointer, but buffer's data was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| else |
| { |
| /* Comparison results with inverted reference data. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| is_ok &= (data[i] == s_reference[s_reference_count - i - 1]); |
| } |
| |
| /* Unmapping with new named buffer unmap function. */ |
| if (GL_TRUE != m_pUnmapNamedBuffer(buffer)) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = false; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| const glw::GLuint MapReadWriteTest::s_reference[] = { |
| 0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 |
| }; //!< Reference data. |
| const glw::GLsizei MapReadWriteTest::s_reference_size = sizeof(s_reference); //!< Reference data size. |
| const glw::GLsizei MapReadWriteTest::s_reference_count = |
| s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count. |
| |
| /******************************** Map Write Only Test Implementation ********************************/ |
| |
| /** @brief Map Write Only Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| MapWriteOnlyTest::MapWriteOnlyTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_map_write_only", "Buffer Objects Map Write Only Test") |
| , m_pNamedBufferData(DE_NULL) |
| , m_pMapNamedBuffer(DE_NULL) |
| , m_pUnmapNamedBuffer(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Map Write Only Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult MapWriteOnlyTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| glw::GLuint buffer = 0; |
| |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer; |
| m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pUnmapNamedBuffer)) |
| { |
| throw 0; |
| } |
| |
| /* Buffer creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Buffer's storage allocation. */ |
| m_pNamedBufferData(buffer, s_reference_size, NULL, GL_DYNAMIC_COPY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| /* Mapping with new named buffer map function. */ |
| glw::GLuint* data = (glw::GLuint*)m_pMapNamedBuffer(buffer, GL_WRITE_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| if (DE_NULL == data) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "glMapNamedBuffer returned NULL pointer, but buffer's data was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| else |
| { |
| /* Reference data upload. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| data[i] = s_reference[i]; |
| } |
| |
| /* Unmapping with new named buffer unmap function. */ |
| if (GL_TRUE != m_pUnmapNamedBuffer(buffer)) |
| { |
| is_ok = false; |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glUnmapNamedBuffer called on mapped buffer has returned GL_FALSE, but GL_TRUE was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| /* Mapping data, the old way. */ |
| gl.bindBuffer(GL_ARRAY_BUFFER, buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed."); |
| |
| data = DE_NULL; |
| |
| data = (glw::GLuint*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed."); |
| |
| /* Comparison results with reference data. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| is_ok &= (data[i] == s_reference[i]); |
| } |
| |
| if (!is_ok) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glMapNamedBuffer, called with GL_WRITE_ONLY access flag, had not stored the reference data." |
| << tcu::TestLog::EndMessage; |
| } |
| |
| gl.unmapBuffer(GL_ARRAY_BUFFER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = false; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| const glw::GLuint MapWriteOnlyTest::s_reference[] = { |
| 0, 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 |
| }; //!< Reference data. |
| const glw::GLsizei MapWriteOnlyTest::s_reference_size = sizeof(s_reference); //!< Reference data size. |
| const glw::GLsizei MapWriteOnlyTest::s_reference_count = |
| s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count. |
| |
| /******************************** Buffers Range Map Read Bit Test Implementation ********************************/ |
| |
| /** @brief Buffers Range Map Read Bit Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| MapRangeReadBitTest::MapRangeReadBitTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_map_range_read_bit", "Buffer Objects Map Range Read Bit Test") |
| , m_pNamedBufferStorage(DE_NULL) |
| , m_pMapNamedBufferRange(DE_NULL) |
| , m_pUnmapNamedBuffer(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Buffers Range Map Read Bit Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult MapRangeReadBitTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| glw::GLuint buffer = 0; |
| |
| m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage; |
| m_pMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGE)gl.mapNamedBufferRange; |
| m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pMapNamedBufferRange) || |
| (DE_NULL == m_pUnmapNamedBuffer)) |
| { |
| throw 0; |
| } |
| |
| glw::GLbitfield access_flags[] = { GL_MAP_READ_BIT, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT, |
| GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT }; |
| |
| glw::GLuint access_flags_count = sizeof(access_flags) / sizeof(access_flags[0]); |
| |
| for (glw::GLuint i = 0; i < access_flags_count; ++i) |
| { |
| /* Buffer creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Buffer's storage allocation and reference data upload. */ |
| m_pNamedBufferStorage(buffer, s_reference_size, s_reference, access_flags[i]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| /* Mapping with first half of named buffer. */ |
| glw::GLuint* data = (glw::GLuint*)m_pMapNamedBufferRange(buffer, 0, s_reference_size / 2, access_flags[i]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed."); |
| |
| /* Check with reference. */ |
| is_ok &= CompareWithReference(data, 0, s_reference_size / 2); |
| |
| /* Unmapping with new named buffer unmap function. */ |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| /* Mapping with second half of named buffer. */ |
| data = (glw::GLuint*)m_pMapNamedBufferRange(buffer, s_reference_size / 2, s_reference_size / 2, |
| access_flags[i]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed."); |
| |
| /* Check with reference. */ |
| is_ok &= CompareWithReference(data, s_reference_size / 2, s_reference_size / 2); |
| |
| /* Unmapping with new named buffer unmap function. */ |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /** @brief Compare array of unsigned integers with subrange of reference values (s_reference). |
| * |
| * @param [in] data Data to be compared. |
| * @param [in] offset Offset in the reference data. |
| * @param [in] length Length of the data to be compared. |
| * |
| * @return True if comparison succeeded, false otherwise. |
| */ |
| bool MapRangeReadBitTest::CompareWithReference(glw::GLuint* data, glw::GLintptr offset, glw::GLsizei length) |
| { |
| if (DE_NULL == data) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "glMapNamedBufferRange called with offset " << offset << " and length " |
| << length << " returned NULL pointer, but buffer's data was expected." << tcu::TestLog::EndMessage; |
| } |
| else |
| { |
| glw::GLuint start = static_cast<glw::GLuint>((offset) / sizeof(s_reference[0])); |
| glw::GLuint end = static_cast<glw::GLuint>((offset + length) / sizeof(s_reference[0])); |
| |
| /* Comparison results with reference data. */ |
| for (glw::GLuint i = start; i < end; ++i) |
| { |
| #if (DE_COMPILER == DE_COMPILER_GCC) |
| #pragma GCC diagnostic push |
| #pragma GCC diagnostic ignored "-Warray-bounds" |
| #endif |
| if (data[i - start] != s_reference[i]) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "glMapNamedBufferRange called with offset " << offset << " and length " |
| << length << " returned pointer to data which is not identical to reference data." |
| << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| #if (DE_COMPILER == DE_COMPILER_GCC) |
| #pragma GCC diagnostic pop |
| #endif |
| } |
| } |
| |
| return true; |
| } |
| |
| const glw::GLuint MapRangeReadBitTest::s_reference[] = { |
| 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 |
| }; //!< Reference data. |
| const glw::GLsizei MapRangeReadBitTest::s_reference_size = sizeof(s_reference); //!< Reference data size. |
| const glw::GLsizei MapRangeReadBitTest::s_reference_count = |
| s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count. |
| |
| /******************************** Buffers Range Map Write Bit Test Implementation ********************************/ |
| |
| /** @brief Buffers Range Map Write Bit Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| MapRangeWriteBitTest::MapRangeWriteBitTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_map_range_write_bit", "Buffer Objects Map Range Write Bit Test") |
| , m_pNamedBufferStorage(DE_NULL) |
| , m_pMapNamedBufferRange(DE_NULL) |
| , m_pUnmapNamedBuffer(DE_NULL) |
| , m_pFlushMappedNamedBufferRange(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Buffers Range Map Read Bit Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult MapRangeWriteBitTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| glw::GLuint buffer = 0; |
| |
| m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage; |
| m_pMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGE)gl.mapNamedBufferRange; |
| m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer; |
| m_pFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGE)gl.flushMappedNamedBufferRange; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pMapNamedBufferRange) || |
| (DE_NULL == m_pUnmapNamedBuffer) || (DE_NULL == m_pFlushMappedNamedBufferRange)) |
| { |
| throw 0; |
| } |
| |
| struct |
| { |
| glw::GLbitfield creation; |
| glw::GLbitfield first_mapping; |
| glw::GLbitfield second_mapping; |
| } access_flags[] = { |
| { GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT }, |
| { GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, |
| GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT }, |
| { GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT, GL_MAP_WRITE_BIT }, |
| { GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT, |
| GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT }, |
| { GL_MAP_WRITE_BIT | GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT } |
| }; |
| |
| glw::GLuint access_flags_count = sizeof(access_flags) / sizeof(access_flags[0]); |
| |
| for (glw::GLuint i = 0; i < access_flags_count; ++i) |
| { |
| /* Buffer creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Buffer's storage allocation and reference data upload. */ |
| m_pNamedBufferStorage(buffer, s_reference_size, DE_NULL, access_flags[i].creation); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage failed."); |
| |
| /* Mapping with first half of named buffer. */ |
| glw::GLuint* data = |
| (glw::GLuint*)m_pMapNamedBufferRange(buffer, 0, s_reference_size / 2, access_flags[i].first_mapping); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed."); |
| |
| /* Write to mapped buffer. */ |
| for (glw::GLsizei j = 0; j < s_reference_count / 2; ++j) |
| { |
| data[j] = s_reference[j]; |
| } |
| |
| /* Flush, if needed. */ |
| glw::GLenum flush_error = GL_NO_ERROR; |
| |
| if (GL_MAP_FLUSH_EXPLICIT_BIT & access_flags[i].first_mapping) |
| { |
| m_pFlushMappedNamedBufferRange(buffer, 0, s_reference_size / 2); |
| |
| flush_error = gl.getError(); |
| } |
| |
| /* Unmapping with new named buffer unmap function. */ |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(flush_error, "glFlushMappedNamedBufferRange failed."); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| /* Mapping with second half of named buffer. */ |
| data = (glw::GLuint*)m_pMapNamedBufferRange(buffer, s_reference_size / 2, s_reference_size / 2, |
| access_flags[i].second_mapping); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBufferRange failed."); |
| |
| /* Write to mapped buffer. */ |
| for (glw::GLsizei j = 0; j < s_reference_count / 2; ++j) |
| { |
| data[j] = s_reference[j + s_reference_count / 2]; |
| } |
| |
| /* Flush, if needed. */ |
| flush_error = GL_NO_ERROR; |
| |
| if (GL_MAP_FLUSH_EXPLICIT_BIT & access_flags[i].second_mapping) |
| { |
| m_pFlushMappedNamedBufferRange(buffer, 0, s_reference_size / 2); |
| |
| flush_error = gl.getError(); |
| } |
| |
| /* Unmapping with new named buffer unmap function. */ |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(flush_error, "glFlushMappedNamedBufferRange failed."); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| /* Check that previous mappings correctly filled buffer with reference data. */ |
| is_ok &= CompareWithReference(buffer, access_flags[i].first_mapping | access_flags[i].second_mapping); |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /** @brief Compare buffer's content with the reference values (s_reference) and log possible failure. |
| * |
| * @param [in] buffer Buffer to be tested. |
| * @param [in] access_flag Access flag used during test's mapping (for failure logging purposes). |
| * |
| * @return True if comparison succeeded, false otherwise. |
| */ |
| bool MapRangeWriteBitTest::CompareWithReference(glw::GLuint buffer, glw::GLbitfield access_flag) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Map buffer with legacy API. */ |
| gl.bindBuffer(GL_ARRAY_BUFFER, buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer failed."); |
| |
| glw::GLuint* data = (glw::GLuint*)gl.mapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer failed."); |
| |
| /* Default return value. */ |
| bool is_ok = true; |
| |
| if (DE_NULL != data) |
| { |
| /* Comparison results with reference data. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| if (data[i] != s_reference[i]) |
| { |
| std::string access_string = "GL_MAP_WRITE_BIT"; |
| |
| if (GL_MAP_INVALIDATE_RANGE_BIT & access_flag) |
| { |
| access_string = "(GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT)"; |
| } |
| |
| if (GL_MAP_INVALIDATE_BUFFER_BIT & access_flag) |
| { |
| access_string = "(GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT)"; |
| } |
| |
| if (GL_MAP_FLUSH_EXPLICIT_BIT & access_flag) |
| { |
| access_string = "(GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT)"; |
| } |
| |
| if (GL_MAP_UNSYNCHRONIZED_BIT & access_flag) |
| { |
| access_string = "(GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT)"; |
| } |
| |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "Test of glMapNamedBufferRange with access flag " << access_string |
| << " failed to fill the buffer with reference data." << tcu::TestLog::EndMessage; |
| |
| is_ok = false; |
| |
| break; |
| } |
| } |
| } |
| |
| /* Unmap buffer. */ |
| gl.unmapBuffer(GL_ARRAY_BUFFER); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer failed."); |
| |
| return is_ok; |
| } |
| |
| const glw::GLuint MapRangeWriteBitTest::s_reference[] = { |
| 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 |
| }; //!< Reference data. |
| const glw::GLsizei MapRangeWriteBitTest::s_reference_size = sizeof(s_reference); //!< Reference data size. |
| const glw::GLsizei MapRangeWriteBitTest::s_reference_count = |
| s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count. |
| |
| /******************************** Get Named Buffer SubData Query Test Implementation ********************************/ |
| |
| /** @brief Get Named Buffer SubData Query Test's static constants. */ |
| const glw::GLuint SubDataQueryTest::s_reference[] = { |
| 1, 2, 4, 8, 16, 64, 128, 256, 512, 1024, 2048, 4096 |
| }; //!< Reference data. |
| const glw::GLsizei SubDataQueryTest::s_reference_size = sizeof(s_reference); //!< Reference data size. |
| const glw::GLsizei SubDataQueryTest::s_reference_count = |
| s_reference_size / sizeof(s_reference[0]); //!< Reference data elements' count. |
| |
| /** @brief Get Named Buffer SubData Query Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| SubDataQueryTest::SubDataQueryTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_get_named_buffer_subdata", "Buffer Objects Get Named Buffer SubData Query Test") |
| , m_pNamedBufferData(DE_NULL) |
| , m_pGetNamedBufferSubData(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Get Named Buffer SubData Query Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult SubDataQueryTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| glw::GLuint buffer = 0; |
| |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATA)gl.getNamedBufferSubData; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pGetNamedBufferSubData)) |
| { |
| throw 0; |
| } |
| |
| /* Buffer creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Buffer's storage allocation and reference data upload. */ |
| m_pNamedBufferData(buffer, s_reference_size, s_reference, GL_DYNAMIC_COPY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferData failed."); |
| |
| /* Mapping with new named buffer map function. */ |
| glw::GLuint data[s_reference_count] = {}; |
| m_pGetNamedBufferSubData(buffer, 0, s_reference_size / 2, data); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedBufferSubData failed."); |
| |
| m_pGetNamedBufferSubData(buffer, s_reference_size / 2, s_reference_size / 2, &data[s_reference_count / 2]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetNamedBufferSubData failed."); |
| |
| /* Comparison results with reference data. */ |
| for (glw::GLsizei i = 0; i < s_reference_count; ++i) |
| { |
| is_ok &= (data[i] == s_reference[i]); |
| } |
| |
| if (!is_ok) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glGetNamedBufferSubData returned data which is not identical to reference data." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = false; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /******************************** Defaults Test Implementation ********************************/ |
| |
| /** @brief Defaults Query Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| DefaultsTest::DefaultsTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_defaults", "Buffer Objects Defaults Test") |
| , m_pNamedBufferData(DE_NULL) |
| , m_pGetNamedBufferParameteri64v(DE_NULL) |
| , m_pGetNamedBufferParameteriv(DE_NULL) |
| , m_pGetNamedBufferPointerv(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Compare value with the reference. |
| * |
| * @param [in] value Value to be compared. |
| * @param [in] reference_value Reference value for comparison. |
| * @param [in] pname_string String of parameter name of the value (for logging). |
| * @param [in] function_string String of function which returned the value (for logging). |
| * |
| * @return True if value is equal to reference value, false otherwise. False solution is logged. |
| */ |
| template <typename T> |
| bool DefaultsTest::CheckValue(const T value, const T reference_value, const glw::GLchar* pname_string, |
| const glw::GLchar* function_string) |
| { |
| if (reference_value != value) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function_string << " called with " |
| << pname_string << " parameter name returned " << value << ", but " |
| << reference_value << " was expected." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| return true; |
| } |
| |
| /** @brief Iterate Defaults Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult DefaultsTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| glw::GLuint buffer = 0; |
| |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64V)gl.getNamedBufferParameteri64v; |
| m_pGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIV)gl.getNamedBufferParameteriv; |
| m_pGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERV)gl.getNamedBufferPointerv; |
| |
| try |
| { |
| if ((DE_NULL == m_pNamedBufferData) || (DE_NULL == m_pGetNamedBufferParameteri64v) || |
| (DE_NULL == m_pGetNamedBufferParameteriv) || (DE_NULL == m_pGetNamedBufferPointerv)) |
| { |
| throw 0; |
| } |
| |
| /* Buffer creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Test data for glGetNamedBufferParameteri*v. */ |
| static const struct |
| { |
| glw::GLenum pname; |
| const glw::GLchar* pname_string; |
| glw::GLint expected_data; |
| } test_values[] = { { GL_BUFFER_SIZE, "GL_BUFFER_SIZE", 0 }, |
| { GL_BUFFER_USAGE, "GL_BUFFER_USAGE", GL_STATIC_DRAW }, |
| { GL_BUFFER_ACCESS, "GL_BUFFER_ACCESS", GL_READ_WRITE }, |
| { GL_BUFFER_ACCESS_FLAGS, "GL_BUFFER_ACCESS_FLAGS", 0 }, |
| { GL_BUFFER_IMMUTABLE_STORAGE, "GL_BUFFER_IMMUTABLE_STORAGE", GL_FALSE }, |
| { GL_BUFFER_MAPPED, "GL_BUFFER_MAPPED", GL_FALSE }, |
| { GL_BUFFER_MAP_OFFSET, "GL_BUFFER_MAP_OFFSET", 0 }, |
| { GL_BUFFER_MAP_LENGTH, "GL_BUFFER_MAP_LENGTH", 0 }, |
| { GL_BUFFER_STORAGE_FLAGS, "GL_BUFFER_STORAGE_FLAGS", 0 } }; |
| |
| static const glw::GLuint test_dictionary_count = sizeof(test_values) / sizeof(test_values[0]); |
| |
| /* Test glGetNamedBufferParameteriv. */ |
| for (glw::GLuint i = 0; i < test_dictionary_count; ++i) |
| { |
| glw::GLint data = -1; |
| |
| m_pGetNamedBufferParameteriv(buffer, test_values[i].pname, &data); |
| |
| is_ok &= CheckParameterError(test_values[i].pname_string, "glGetNamedBufferParameteriv"); |
| |
| is_ok &= CheckValue<glw::GLint>(data, test_values[i].expected_data, test_values[i].pname_string, |
| "glGetNamedBufferParameteriv"); |
| } |
| |
| /* Test glGetNamedBufferParameteri64v. */ |
| for (glw::GLuint i = 0; i < test_dictionary_count; ++i) |
| { |
| glw::GLint64 data = -1; |
| |
| m_pGetNamedBufferParameteri64v(buffer, test_values[i].pname, &data); |
| |
| is_ok &= CheckParameterError(test_values[i].pname_string, "glGetNamedBufferParameteri64v"); |
| |
| is_ok &= CheckValue<glw::GLint64>(data, (glw::GLint64)test_values[i].expected_data, |
| test_values[i].pname_string, "glGetNamedBufferParameteri64v"); |
| } |
| |
| /* Test glGetNamedBufferPointerv. */ |
| { |
| glw::GLvoid* data = (glw::GLvoid*)1; |
| |
| m_pGetNamedBufferPointerv(buffer, GL_BUFFER_MAP_POINTER, &data); |
| |
| is_ok &= CheckParameterError("GL_BUFFER_MAP_POINTER", "glGetNamedBufferPointer"); |
| |
| is_ok &= CheckValue<glw::GLvoid*>(data, (glw::GLvoid*)DE_NULL, "GL_BUFFER_MAP_POINTER", |
| "glGetNamedBufferParameteriv"); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean up. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /** @brief Check for GL error and log. |
| * |
| * @param [in] pname_string String of parameter name of the value (for logging). |
| * @param [in] function_string String of function which returned the value (for logging). |
| * |
| * @return True if error was generated, false otherwise. False solution is logged. |
| */ |
| bool DefaultsTest::CheckParameterError(const glw::GLchar* pname_string, const glw::GLchar* function_string) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Error check. */ |
| if (glw::GLenum error = gl.getError()) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function_string << " called with " |
| << pname_string << " parameter name unexpectedly returned " |
| << glu::getErrorStr(error) << "error." << tcu::TestLog::EndMessage; |
| |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /******************************** Errors Test Implementation ********************************/ |
| |
| /** @brief Errors Query Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| ErrorsTest::ErrorsTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_errors", "Buffer Objects Errors Test") |
| , m_pClearNamedBufferData(DE_NULL) |
| , m_pClearNamedBufferSubData(DE_NULL) |
| , m_pCopyNamedBufferSubData(DE_NULL) |
| , m_pFlushMappedNamedBufferRange(DE_NULL) |
| , m_pGetNamedBufferParameteri64v(DE_NULL) |
| , m_pGetNamedBufferParameteriv(DE_NULL) |
| , m_pGetNamedBufferPointerv(DE_NULL) |
| , m_pGetNamedBufferSubData(DE_NULL) |
| , m_pMapNamedBuffer(DE_NULL) |
| , m_pMapNamedBufferRange(DE_NULL) |
| , m_pNamedBufferData(DE_NULL) |
| , m_pNamedBufferStorage(DE_NULL) |
| , m_pNamedBufferSubData(DE_NULL) |
| , m_pUnmapNamedBuffer(DE_NULL) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Iterate Errors Test cases. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult ErrorsTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* API function pointers setup. */ |
| m_pClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATA)gl.clearNamedBufferData; |
| m_pClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATA)gl.clearNamedBufferSubData; |
| m_pCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATA)gl.copyNamedBufferSubData; |
| m_pFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGE)gl.flushMappedNamedBufferRange; |
| m_pGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64V)gl.getNamedBufferParameteri64v; |
| m_pGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIV)gl.getNamedBufferParameteriv; |
| m_pGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERV)gl.getNamedBufferPointerv; |
| m_pGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATA)gl.getNamedBufferSubData; |
| m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer; |
| m_pMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGE)gl.mapNamedBufferRange; |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage; |
| m_pNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATA)gl.namedBufferSubData; |
| m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer; |
| |
| try |
| { |
| /* API function pointers check. */ |
| if ((DE_NULL == m_pClearNamedBufferData) || (DE_NULL == m_pClearNamedBufferSubData) || |
| (DE_NULL == m_pCopyNamedBufferSubData) || (DE_NULL == m_pFlushMappedNamedBufferRange) || |
| (DE_NULL == m_pGetNamedBufferParameteri64v) || (DE_NULL == m_pGetNamedBufferParameteriv) || |
| (DE_NULL == m_pGetNamedBufferPointerv) || (DE_NULL == m_pGetNamedBufferSubData) || |
| (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pMapNamedBufferRange) || (DE_NULL == m_pNamedBufferData) || |
| (DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pNamedBufferSubData) || |
| (DE_NULL == m_pUnmapNamedBuffer)) |
| { |
| throw 0; |
| } |
| |
| /* Running test cases. Cleaning errors. */ |
| is_ok &= TestErrorsOfClearNamedBufferData(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfClearNamedBufferSubData(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfCopyNamedBufferSubData(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfCreateBuffers(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfFlushMappedNamedBufferRange(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfGetNamedBufferParameter(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfGetNamedBufferPointerv(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfGetNamedBufferSubData(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfMapNamedBuffer(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfMapNamedBufferRange(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfNamedBufferData(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfNamedBufferStorage(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfNamedBufferSubData(); |
| while (gl.getError()) |
| ; |
| is_ok &= TestErrorsOfUnmapNamedBuffer(); |
| while (gl.getError()) |
| ; |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /** Check if error was generated and if it is equal to expected value. Log possible failure. |
| * |
| * @param [in] function_name Tested Function. |
| * @param [in] expected_error Expected error function. |
| * @param [in] when_shall_be_generated Description when shall the error occure. |
| * |
| * @return True if GL error is equal to the expected value, false otherwise. |
| */ |
| bool ErrorsTest::ErrorCheckAndLog(const glw::GLchar* function_name, const glw::GLenum expected_error, |
| const glw::GLchar* when_shall_be_generated) |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Error value storage. */ |
| glw::GLenum error = GL_NO_ERROR; |
| |
| /* Error comparision. */ |
| if (expected_error != (error = gl.getError())) |
| { |
| /* Log. */ |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << function_name << " does not generate " |
| << glu::getErrorStr(expected_error) << when_shall_be_generated |
| << "The error value of " << glu::getErrorStr(error) << " was observed." |
| << tcu::TestLog::EndMessage; |
| |
| /* Error cleanup. */ |
| while (gl.getError()) |
| ; |
| |
| /* Check failed. */ |
| return false; |
| } |
| |
| /* Error was equal to expected. */ |
| return true; |
| } |
| |
| /** @brief Test Errors Of ClearNamedBufferData function. |
| * |
| * Check that INVALID_OPERATION is generated by ClearNamedBufferData if |
| * buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_ENUM is generated by ClearNamedBufferData if |
| * internal format is not one of the valid sized internal formats listed in |
| * the table above. |
| * |
| * Check that INVALID_OPERATION is generated by ClearNamedBufferData if |
| * any part of the specified range of the buffer object is mapped with |
| * MapBufferRange or MapBuffer, unless it was mapped with the |
| * MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags. |
| * |
| * Check that INVALID_VALUE is generated by ClearNamedBufferData if |
| * format is not a valid format, or type is not a valid type. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfClearNamedBufferData() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLbyte dummy_data = 0; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBufferStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferData(not_a_buffer_name, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test invalid sized internal format error behavior. */ |
| { |
| /* Prepare for invalid sized internal format error behavior verification. */ |
| static const glw::GLenum valid_internal_formats[] = { |
| GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I, |
| GL_R8UI, GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F, |
| GL_RG8I, GL_RG16I, GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F, |
| GL_RGB32I, GL_RGB32UI, GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I, |
| GL_RGBA16I, GL_RGBA32I, GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI, GL_NONE |
| }; |
| static const glw::GLenum valid_internal_formats_last = |
| sizeof(valid_internal_formats) / sizeof(valid_internal_formats[0]) - 1; |
| |
| glw::GLenum invalid_internal_format = 0; |
| |
| while (&valid_internal_formats[valid_internal_formats_last] != |
| std::find(&valid_internal_formats[0], &valid_internal_formats[valid_internal_formats_last], |
| (++invalid_internal_format))) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferData(buffer, invalid_internal_format, GL_RED, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_ENUM, |
| " if internal format is not one of the valid sized internal formats " |
| "(GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I, GL_R8UI," |
| " GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F, GL_RG8I, GL_RG16I," |
| " GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F, GL_RGB32I, GL_RGB32UI," |
| " GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I, GL_RGBA16I, GL_RGBA32I," |
| " GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI)."); |
| } |
| |
| /* Test of mapped buffer clear error behavior verification (glMapNamedBuffer version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBuffer(buffer, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pClearNamedBufferData(buffer, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_OPERATION, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBuffer, unless it was mapped with " |
| "the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of mapped buffer clear error behavior verification (glMapNamedBufferRange version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pClearNamedBufferData(buffer, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_INVALID_OPERATION, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBufferRange, unless it was mapped with " |
| "the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of persistently mapped buffer clear error with behavior verification (glMapNamedBufferRange version). */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pClearNamedBufferData(buffer, GL_R8, GL_RED, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferData", GL_NO_ERROR, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBuffer with the MAP_PERSISTENT_BIT" |
| " bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test invalid format error behavior. */ |
| { |
| /* Prepare for invalid format error behavior verification. */ |
| static const glw::GLenum valid_formats[] = { GL_RED, GL_RG, |
| GL_RGB, GL_BGR, |
| GL_RGBA, GL_BGRA, |
| GL_RED_INTEGER, GL_RG_INTEGER, |
| GL_RGB_INTEGER, GL_BGR_INTEGER, |
| GL_RGBA_INTEGER, GL_BGRA_INTEGER, |
| GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, |
| GL_DEPTH_STENCIL }; |
| static const glw::GLenum valid_formats_last = sizeof(valid_formats) / sizeof(valid_formats[0]) - 1; |
| |
| glw::GLenum invalid_format = 0; |
| |
| while (&valid_formats[valid_formats_last] != |
| std::find(&valid_formats[0], &valid_formats[valid_formats_last], (++invalid_format))) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferData(buffer, GL_R8, invalid_format, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glClearNamedBufferData", GL_INVALID_VALUE, |
| " if format is not a valid format " |
| "(one of GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, " |
| "GL_RED_INTEGER, GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, GL_RGBA_INTEGER, GL_BGRA_INTEGER, " |
| "GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL)."); |
| } |
| |
| /* Test invalid type error behavior. */ |
| { |
| /* Prepare for invalid type error behavior verification. */ |
| static const glw::GLenum valid_types[] = { GL_RED, GL_RG, |
| GL_RGB, GL_BGR, |
| GL_RGBA, GL_BGRA, |
| GL_RED_INTEGER, GL_RG_INTEGER, |
| GL_RGB_INTEGER, GL_BGR_INTEGER, |
| GL_RGBA_INTEGER, GL_BGRA_INTEGER, |
| GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, |
| GL_DEPTH_STENCIL }; |
| static const glw::GLenum valid_types_last = sizeof(valid_types) / sizeof(valid_types[0]) - 1; |
| |
| glw::GLenum invalid_type = 0; |
| |
| while (&valid_types[valid_types_last] != |
| std::find(&valid_types[0], &valid_types[valid_types_last], (++invalid_type))) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferData(buffer, GL_R8, GL_RED, invalid_type, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glClearNamedBufferData", GL_INVALID_VALUE, |
| " if format is not a valid type " |
| "(one of GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, " |
| "GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, " |
| "GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, " |
| "GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, " |
| "GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, " |
| "GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, and GL_UNSIGNED_INT_2_10_10_10_REV)."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of ClearNamedBufferSubData function. |
| * |
| * Check that INVALID_OPERATION is generated by ClearNamedBufferSubData |
| * if buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_ENUM is generated by ClearNamedBufferSubData if |
| * internal format is not one of the valid sized internal formats listed in |
| * the table above. |
| * |
| * Check that INVALID_VALUE is generated by ClearNamedBufferSubData if |
| * offset or range are not multiples of the number of basic machine units |
| * per-element for the internal format specified by internal format. This |
| * value may be computed by multiplying the number of components for |
| * internal format from the table by the size of the base type from the |
| * specification table. |
| * |
| * Check that INVALID_VALUE is generated by ClearNamedBufferSubData if |
| * offset or size is negative, or if offset+size is greater than the value |
| * of BUFFER_SIZE for the buffer object. |
| * |
| * Check that INVALID_OPERATION is generated by ClearNamedBufferSubData |
| * if any part of the specified range of the buffer object is mapped with |
| * MapBufferRange or MapBuffer, unless it was mapped with the |
| * MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags. |
| * |
| * Check that INVALID_VALUE is generated by ClearNamedBufferSubData if format is not |
| * a valid format, or type is not a valid type. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfClearNamedBufferSubData() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferSubData(not_a_buffer_name, GL_R8, 0, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, |
| &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test invalid sized internal format error behavior. */ |
| { |
| /* Prepare for invalid sized internal format error behavior verification. */ |
| static const glw::GLenum valid_internal_formats[] = { |
| GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I, |
| GL_R8UI, GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F, |
| GL_RG8I, GL_RG16I, GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F, |
| GL_RGB32I, GL_RGB32UI, GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I, |
| GL_RGBA16I, GL_RGBA32I, GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI, GL_NONE |
| }; |
| static const glw::GLenum valid_internal_formats_last = |
| sizeof(valid_internal_formats) / sizeof(valid_internal_formats[0]) - 1; |
| |
| glw::GLenum invalid_internal_format = 0; |
| |
| while (&valid_internal_formats[valid_internal_formats_last] != |
| std::find(&valid_internal_formats[0], &valid_internal_formats[valid_internal_formats_last], |
| (++invalid_internal_format))) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferData(buffer, invalid_internal_format, GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_ENUM, |
| " if internal format is not one of the valid sized internal formats " |
| "(GL_R8, GL_R16, GL_R16F, GL_R32F, GL_R8I, GL_R16I, GL_R32I, GL_R8UI," |
| " GL_R16UI, GL_R32UI, GL_RG8, GL_RG16, GL_RG16F, GL_RG32F, GL_RG8I, GL_RG16I," |
| " GL_RG32I, GL_RG8UI, GL_RG16UI, GL_RG32UI, GL_RGB32F, GL_RGB32I, GL_RGB32UI," |
| " GL_RGBA8, GL_RGBA16, GL_RGBA16F, GL_RGBA32F, GL_RGBA8I, GL_RGBA16I, GL_RGBA32I," |
| " GL_RGBA8UI, GL_RGBA16UI, GL_RGBA32UI)."); |
| } |
| |
| /* Test incorrect offset alignment error behavior. */ |
| { |
| /* Test. */ |
| m_pClearNamedBufferSubData(buffer, GL_RGBA8, sizeof(dummy_data[0]), sizeof(dummy_data), GL_RGBA, |
| GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE, |
| "if offset is not multiples of the number of basic machine units (GLubyte)" |
| "per-element for the internal format (GL_RGBA) specified by internal format."); |
| } |
| |
| /* Test incorrect range alignment error behavior. */ |
| { |
| m_pClearNamedBufferSubData(buffer, GL_RGBA8, 0, sizeof(dummy_data) - sizeof(dummy_data[0]), GL_RGBA, |
| GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE, |
| "if range is not multiples of the number of basic machine units (GLubyte)" |
| "per-element for the internal format (GL_RGBA) specified by internal format."); |
| } |
| |
| /* Test negative offset error behavior. */ |
| { |
| /* Test. */ |
| m_pClearNamedBufferSubData(buffer, GL_R8, -1, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE, " if offset or size is negative."); |
| } |
| |
| /* Test negative size error behavior. */ |
| { |
| /* Test. */ |
| m_pClearNamedBufferSubData(buffer, GL_R8, 0, -((glw::GLsizei)sizeof(dummy_data)), GL_RGBA, GL_UNSIGNED_BYTE, |
| &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_VALUE, " if offset or size is negative."); |
| } |
| |
| /* Test size overflow error behavior. */ |
| { |
| /* Test. */ |
| m_pClearNamedBufferSubData(buffer, GL_R8, 0, 2 * sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, |
| &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glClearNamedBufferSubData", GL_INVALID_VALUE, |
| " if offset+size is greater than the value of BUFFER_SIZE for the specified buffer object."); |
| } |
| |
| /* Test of mapped buffer clear error behavior verification (glMapNamedBuffer version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBuffer(buffer, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pClearNamedBufferSubData(buffer, GL_R8, 0, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_OPERATION, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBuffer, unless it was mapped with " |
| "the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of mapped buffer clear error behavior verification (glMapNamedBufferRange version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pClearNamedBufferSubData(buffer, GL_R8, 0, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_INVALID_OPERATION, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBufferRange, unless it was mapped with " |
| "the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of persistently mapped buffer clear error with behavior verification (glMapNamedBufferRange version). */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pClearNamedBufferSubData(buffer, GL_R8, 0, sizeof(dummy_data), GL_RGBA, GL_UNSIGNED_BYTE, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glClearNamedBufferSubData", GL_NO_ERROR, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBuffer with the MAP_PERSISTENT_BIT" |
| " bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test invalid format error behavior. */ |
| { |
| /* Prepare for invalid format error behavior verification. */ |
| static const glw::GLenum valid_formats[] = { GL_RED, GL_RG, |
| GL_RGB, GL_BGR, |
| GL_RGBA, GL_BGRA, |
| GL_RED_INTEGER, GL_RG_INTEGER, |
| GL_RGB_INTEGER, GL_BGR_INTEGER, |
| GL_RGBA_INTEGER, GL_BGRA_INTEGER, |
| GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, |
| GL_DEPTH_STENCIL }; |
| static const glw::GLenum valid_formats_last = sizeof(valid_formats) / sizeof(valid_formats[0]) - 1; |
| |
| glw::GLenum invalid_format = 0; |
| |
| while (&valid_formats[valid_formats_last] != |
| std::find(&valid_formats[0], &valid_formats[valid_formats_last], (++invalid_format))) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferSubData(buffer, GL_R8, 0, sizeof(dummy_data), invalid_format, GL_UNSIGNED_BYTE, |
| &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glClearNamedBufferSubData", GL_INVALID_VALUE, |
| " if format is not a valid format " |
| "(one of GL_RED, GL_RG, GL_RGB, GL_BGR, GL_RGBA, GL_BGRA, " |
| "GL_RED_INTEGER, GL_RG_INTEGER, GL_RGB_INTEGER, GL_BGR_INTEGER, GL_RGBA_INTEGER, GL_BGRA_INTEGER, " |
| "GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL)."); |
| } |
| |
| /* Test invalid type error behavior. */ |
| { |
| /* Prepare for invalid type error behavior verification. */ |
| static const glw::GLenum valid_types[] = { GL_RED, GL_RG, |
| GL_RGB, GL_BGR, |
| GL_RGBA, GL_BGRA, |
| GL_RED_INTEGER, GL_RG_INTEGER, |
| GL_RGB_INTEGER, GL_BGR_INTEGER, |
| GL_RGBA_INTEGER, GL_BGRA_INTEGER, |
| GL_STENCIL_INDEX, GL_DEPTH_COMPONENT, |
| GL_DEPTH_STENCIL, GL_NONE }; |
| static const glw::GLenum valid_types_last = sizeof(valid_types) / sizeof(valid_types[0]) - 1; |
| |
| glw::GLenum invalid_type = 0; |
| |
| while (&valid_types[valid_types_last] != |
| std::find(&valid_types[0], &valid_types[valid_types_last], (++invalid_type))) |
| ; |
| |
| /* Test. */ |
| m_pClearNamedBufferSubData(buffer, GL_R8, 0, sizeof(dummy_data), GL_RGBA, invalid_type, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glClearNamedBufferSubData", GL_INVALID_VALUE, |
| " if format is not a valid type " |
| "(one of GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, " |
| "GL_SHORT, GL_UNSIGNED_INT, GL_INT, GL_FLOAT, GL_UNSIGNED_BYTE_3_3_2, " |
| "GL_UNSIGNED_BYTE_2_3_3_REV, GL_UNSIGNED_SHORT_5_6_5, " |
| "GL_UNSIGNED_SHORT_5_6_5_REV, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, " |
| "GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, GL_UNSIGNED_INT_8_8_8_8, " |
| "GL_UNSIGNED_INT_8_8_8_8_REV, GL_UNSIGNED_INT_10_10_10_2, and GL_UNSIGNED_INT_2_10_10_10_REV)."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of CopyNamedBufferSubData function. |
| * |
| * Check that INVALID_OPERATION is generated by CopyNamedBufferSubData if readBuffer |
| * or writeBuffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_VALUE is generated by CopyNamedBufferSubData if any of |
| * readOffset, writeOffset or size is negative, if readOffset+size is |
| * greater than the size of the source buffer object (its value of |
| * BUFFER_SIZE), or if writeOffset+size is greater than the size of the |
| * destination buffer object. |
| * |
| * Check that INVALID_VALUE is generated by CopyNamedBufferSubData if the |
| * source and destination are the same buffer object, and the ranges |
| * [readOffset,readOffset+size) and [writeOffset,writeOffset+size) overlap. |
| * |
| * Check that INVALID_OPERATION is generated by CopyNamedBufferSubData if |
| * either the source or destination buffer object is mapped with |
| * MapBufferRange or MapBuffer, unless they were mapped with the |
| * MAP_PERSISTENT bit set in the MapBufferRange access flags. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfCopyNamedBufferSubData() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer_r = 0; |
| glw::GLuint buffer_w = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer_r); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer_r, sizeof(dummy_data), &dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| gl.createBuffers(1, &buffer_w); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer_w, sizeof(dummy_data), &dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pCopyNamedBufferSubData(not_a_buffer_name, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_OPERATION, |
| " if readBuffer is not the name of an existing buffer object."); |
| |
| m_pCopyNamedBufferSubData(buffer_r, not_a_buffer_name, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_OPERATION, |
| " if writeBuffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test negative read offset error behavior. */ |
| { |
| /* Test. */ |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, -1, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_VALUE, "if readOffset is negative."); |
| } |
| |
| /* Test negative write offset error behavior. */ |
| { |
| /* Test. */ |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, -1, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_VALUE, "if writeOffset is negative."); |
| } |
| |
| /* Test negative size error behavior. */ |
| { |
| /* Test. */ |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, -1); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_VALUE, "if size is negative."); |
| } |
| |
| /* Test overflow size error behavior. */ |
| { |
| /* Test. */ |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, 2 * sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_VALUE, |
| " if size is greater than the size of the source buffer object."); |
| } |
| |
| /* Test overflow read offset and size error behavior. */ |
| { |
| /* Test. */ |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, sizeof(dummy_data) / 2, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_VALUE, |
| " if readOffset+size is greater than the size of the source buffer object."); |
| } |
| |
| /* Test overflow write offset and size error behavior. */ |
| { |
| /* Test. */ |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, sizeof(dummy_data) / 2, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_VALUE, |
| " if writeOffset+size is greater than the size of the source buffer object."); |
| } |
| |
| /* Test same buffer overlapping error behavior. */ |
| { |
| /* Test. */ |
| m_pCopyNamedBufferSubData(buffer_w, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_VALUE, |
| " if the source and destination are the same buffer object, and the ranges" |
| " [readOffset,readOffset+size) and [writeOffset,writeOffset+size) overlap."); |
| } |
| |
| /* Test of mapped read buffer copy error behavior verification (glMapNamedBuffer version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBuffer(buffer_r, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_OPERATION, |
| " if the source buffer object is mapped with MapBuffer."); |
| |
| m_pUnmapNamedBuffer(buffer_r); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of mapped write buffer copy error behavior verification (glMapNamedBuffer version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBuffer(buffer_w, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_OPERATION, |
| " if the destination buffer object is mapped with MapBuffer."); |
| |
| m_pUnmapNamedBuffer(buffer_w); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of mapped read buffer copy error behavior verification (glMapNamedBufferRange version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer_r, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_OPERATION, |
| " if the source buffer object is mapped with MapBuffer."); |
| |
| m_pUnmapNamedBuffer(buffer_r); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of mapped write buffer copy error behavior verification (glMapNamedBufferRange version). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer_w, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_INVALID_OPERATION, |
| " if the destination buffer object is mapped with MapBuffer."); |
| |
| m_pUnmapNamedBuffer(buffer_w); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of persistently mapped read buffer copy error with behavior verification. */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer_r, 0, sizeof(dummy_data), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_NO_ERROR, |
| " if the source buffer object is mapped using " |
| "MapBufferRange with the MAP_PERSISTENT bit " |
| "set in the access flags."); |
| |
| m_pUnmapNamedBuffer(buffer_r); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of persistently mapped write buffer copy error with behavior verification. */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer_w, 0, sizeof(dummy_data), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pCopyNamedBufferSubData(buffer_r, buffer_w, 0, 0, sizeof(dummy_data)); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| is_ok &= ErrorCheckAndLog("glCopyNamedBufferSubData", GL_NO_ERROR, |
| " if the destination buffer object is mapped using " |
| "MapBufferRange with the MAP_PERSISTENT bit " |
| "set in the access flags."); |
| |
| m_pUnmapNamedBuffer(buffer_w); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer_r) |
| { |
| gl.deleteBuffers(1, &buffer_r); |
| |
| buffer_r = 0; |
| } |
| |
| if (buffer_r) |
| { |
| gl.deleteBuffers(1, &buffer_r); |
| |
| buffer_r = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of CreateBuffers function. |
| * |
| * Check that INVALID_VALUE is generated by CreateBuffers if n is negative. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfCreateBuffers() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| |
| /* Test. */ |
| glw::GLuint buffer = 0; |
| |
| gl.createBuffers(-1, &buffer); |
| |
| is_ok &= ErrorCheckAndLog("glCreateBuffers", GL_INVALID_VALUE, " if n is negative."); |
| |
| /* Sanity check. */ |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| /* Possible error cleanup. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of FlushMappedNamedBufferRange function. |
| * |
| * Check that INVALID_OPERATION is generated by FlushMappedNamedBufferRange |
| * if buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_VALUE is generated by FlushMappedNamedBufferRange if |
| * offset or length is negative, or if offset + length exceeds the size of |
| * the mapping. |
| * |
| * Check that INVALID_OPERATION is generated by FlushMappedNamedBufferRange |
| * if the buffer object is not mapped, or is mapped without the |
| * MAP_FLUSH_EXPLICIT_BIT flag. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfFlushMappedNamedBufferRange() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name flush error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pFlushMappedNamedBufferRange(not_a_buffer_name, 0, 1); |
| |
| is_ok &= ErrorCheckAndLog("glFlushMappedNamedBufferRange", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test negative offset flush error behavior. */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pFlushMappedNamedBufferRange(buffer, -1, 1); |
| |
| is_ok &= ErrorCheckAndLog("glFlushMappedNamedBufferRange", GL_INVALID_VALUE, " if offset is negative."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test negative length flush error behavior. */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pFlushMappedNamedBufferRange(buffer, 0, -1); |
| |
| is_ok &= ErrorCheckAndLog("glFlushMappedNamedBufferRange", GL_INVALID_VALUE, " if length is negative."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test length exceeds the mapping size flush error behavior. */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data) / 2, GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pFlushMappedNamedBufferRange(buffer, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glFlushMappedNamedBufferRange", GL_INVALID_VALUE, |
| " if length exceeds the size of the mapping."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test offset + length exceeds the mapping size flush error behavior. */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pFlushMappedNamedBufferRange(buffer, 1, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glFlushMappedNamedBufferRange", GL_INVALID_VALUE, |
| " if offset + length exceeds the size of the mapping."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test not mapped buffer flush error behavior. */ |
| { |
| m_pFlushMappedNamedBufferRange(buffer, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glFlushMappedNamedBufferRange", GL_INVALID_OPERATION, |
| " if the buffer object is not mapped."); |
| } |
| |
| /* Test buffer flush without the MAP_FLUSH_EXPLICIT_BIT error behavior. */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_WRITE_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pFlushMappedNamedBufferRange(buffer, 0, sizeof(dummy_data)); |
| |
| is_ok &= ErrorCheckAndLog("glFlushMappedNamedBufferRange", GL_INVALID_OPERATION, |
| " if the buffer is mapped without the MAP_FLUSH_EXPLICIT_BIT flag."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of GetNamedBufferParameteriv |
| * and GetNamedBufferParameteri64v functions. |
| * |
| * Check that INVALID_OPERATION is generated by GetNamedBufferParameter* if |
| * buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_ENUM is generated by GetNamedBufferParameter* if |
| * pname is not one of the buffer object parameter names: BUFFER_ACCESS, |
| * BUFFER_ACCESS_FLAGS, BUFFER_IMMUTABLE_STORAGE, BUFFER_MAPPED, |
| * BUFFER_MAP_LENGTH, BUFFER_MAP_OFFSET, BUFFER_SIZE, BUFFER_STORAGE_FLAGS, |
| * BUFFER_USAGE. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfGetNamedBufferParameter() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name in GetNamedBufferParameteriv function error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| glw::GLint value = 0; |
| |
| /* Test. */ |
| m_pGetNamedBufferParameteriv(not_a_buffer_name, GL_BUFFER_MAPPED, &value); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferParameteriv", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test invalid buffer name in GetNamedBufferParameteri64v function error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| glw::GLint64 value = 0; |
| |
| /* Test. */ |
| m_pGetNamedBufferParameteri64v(not_a_buffer_name, GL_BUFFER_MAPPED, &value); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferParameteri64v", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test invalid parameter name in GetNamedBufferParameteriv function error behavior. */ |
| { |
| /* Prepare for invalid parameter name error behavior verification. */ |
| static const glw::GLenum valid_parameters[] = { |
| GL_BUFFER_ACCESS, GL_BUFFER_ACCESS_FLAGS, GL_BUFFER_IMMUTABLE_STORAGE, |
| GL_BUFFER_MAPPED, GL_BUFFER_MAP_LENGTH, GL_BUFFER_MAP_OFFSET, |
| GL_BUFFER_SIZE, GL_BUFFER_STORAGE_FLAGS, GL_BUFFER_USAGE, |
| GL_NONE |
| }; |
| static const glw::GLenum valid_parameters_last = sizeof(valid_parameters) / sizeof(valid_parameters[0]) - 1; |
| |
| glw::GLint value = 0; |
| |
| glw::GLenum invalid_parameter = 0; |
| |
| while (&valid_parameters[valid_parameters_last] != |
| std::find(&valid_parameters[0], &valid_parameters[valid_parameters_last], (++invalid_parameter))) |
| ; |
| |
| /* Test. */ |
| m_pGetNamedBufferParameteriv(buffer, invalid_parameter, &value); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferParameteriv", GL_INVALID_ENUM, |
| " if pname is not one of the buffer object parameter names: BUFFER_ACCESS," |
| " BUFFER_ACCESS_FLAGS, BUFFER_IMMUTABLE_STORAGE, BUFFER_MAPPED," |
| " BUFFER_MAP_LENGTH, BUFFER_MAP_OFFSET, BUFFER_SIZE, BUFFER_STORAGE_FLAGS," |
| " BUFFER_USAGE."); |
| } |
| |
| /* Test invalid parameter name in GetNamedBufferParameteri64v function error behavior. */ |
| { |
| /* Prepare for invalid parameter name error behavior verification. */ |
| static const glw::GLenum valid_parameters[] = { |
| GL_BUFFER_ACCESS, GL_BUFFER_ACCESS_FLAGS, GL_BUFFER_IMMUTABLE_STORAGE, |
| GL_BUFFER_MAPPED, GL_BUFFER_MAP_LENGTH, GL_BUFFER_MAP_OFFSET, |
| GL_BUFFER_SIZE, GL_BUFFER_STORAGE_FLAGS, GL_BUFFER_USAGE, |
| GL_NONE |
| }; |
| static const glw::GLenum valid_parameters_last = sizeof(valid_parameters) / sizeof(valid_parameters[0]) - 1; |
| |
| glw::GLint64 value = 0; |
| |
| glw::GLenum invalid_parameter = 0; |
| |
| while (&valid_parameters[valid_parameters_last] != |
| std::find(&valid_parameters[0], &valid_parameters[valid_parameters_last], (++invalid_parameter))) |
| ; |
| |
| /* Test. */ |
| m_pGetNamedBufferParameteri64v(buffer, invalid_parameter, &value); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferParameteri64v", GL_INVALID_ENUM, |
| " if pname is not one of the buffer object parameter names: BUFFER_ACCESS," |
| " BUFFER_ACCESS_FLAGS, BUFFER_IMMUTABLE_STORAGE, BUFFER_MAPPED," |
| " BUFFER_MAP_LENGTH, BUFFER_MAP_OFFSET, BUFFER_SIZE, BUFFER_STORAGE_FLAGS," |
| " BUFFER_USAGE."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of GetNamedBufferPointerv function. |
| * |
| * Check that INVALID_OPERATION is generated by GetNamedBufferPointerv |
| * if buffer is not the name of an existing buffer object. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfGetNamedBufferPointerv() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name in GetNamedBufferPointerv function error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| glw::GLvoid* pointer = DE_NULL; |
| |
| /* Test. */ |
| m_pGetNamedBufferPointerv(not_a_buffer_name, GL_BUFFER_MAP_POINTER, &pointer); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferPointerv", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of GetNamedBufferSubData function. |
| * |
| * Check that INVALID_OPERATION is generated by GetNamedBufferSubData if |
| * buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_VALUE is generated by GetNamedBufferSubData if offset |
| * or size is negative, or if offset+size is greater than the value of |
| * BUFFER_SIZE for the buffer object. |
| * |
| * Check that INVALID_OPERATION is generated by GetNamedBufferSubData if |
| * the buffer object is mapped with MapBufferRange or MapBuffer, unless it |
| * was mapped with the MAP_PERSISTENT_BIT bit set in the MapBufferRange |
| * access flags. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfGetNamedBufferSubData() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name in pGetNamedBufferSubData function error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| m_pGetNamedBufferSubData(not_a_buffer_name, 0, sizeof(dummy_data_query), dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test negative offset error behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| m_pGetNamedBufferSubData(buffer, -1, sizeof(dummy_data_query), dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_VALUE, " if offset is negative."); |
| } |
| |
| /* Test negative size error behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| m_pGetNamedBufferSubData(buffer, 0, -1, dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_VALUE, " if size is negative."); |
| } |
| |
| /* Test size overflow error behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| m_pGetNamedBufferSubData(buffer, 0, 2 * sizeof(dummy_data_query), dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_VALUE, |
| " if size is greater than the value of BUFFER_SIZE for the buffer object."); |
| } |
| |
| /* Test offset+size overflow error behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| m_pGetNamedBufferSubData(buffer, sizeof(dummy_data_query) / 2, sizeof(dummy_data_query), dummy_data_query); |
| |
| is_ok &= |
| ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_VALUE, |
| " if offset+size is greater than the value of BUFFER_SIZE for the buffer object."); |
| } |
| |
| /* Test offset overflow error behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| m_pGetNamedBufferSubData(buffer, sizeof(dummy_data_query) + 1, 0, dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_VALUE, |
| " if offset is greater than the value of BUFFER_SIZE for the buffer object."); |
| } |
| |
| /* Test mapped buffer query error behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| (void)(glw::GLbyte*) m_pMapNamedBuffer(buffer, GL_WRITE_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pGetNamedBufferSubData(buffer, 0, sizeof(dummy_data_query), dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_OPERATION, |
| " if the buffer object is mapped with MapBufferRange."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test mapped buffer query error behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| (void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_WRITE_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pGetNamedBufferSubData(buffer, 0, sizeof(dummy_data_query), dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog("glGetNamedBufferSubData", GL_INVALID_OPERATION, |
| " if the buffer object is mapped with MapBufferRange."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test persistently mapped buffer query behavior. */ |
| { |
| /* Query storage. */ |
| glw::GLubyte dummy_data_query[sizeof(dummy_data) / sizeof(dummy_data[0])] = {}; |
| |
| /* Test. */ |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pGetNamedBufferSubData(buffer, 0, sizeof(dummy_data_query), dummy_data_query); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glGetNamedBufferSubData", GL_NO_ERROR, |
| " if the buffer object is mapped with MapBufferRange with GL_MAP_PERSISTENT_BIT flag."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of MapNamedBuffer function. |
| * |
| * Check that INVALID_OPERATION is generated by MapNamedBuffer if buffer is |
| * not the name of an existing buffer object. |
| * |
| * Check that INVALID_ENUM is generated by MapNamedBuffer if access is not |
| * READ_ONLY, WRITE_ONLY, or READ_WRITE. |
| * |
| * Check that INVALID_OPERATION is generated by MapNamedBuffer if the |
| * buffer object is in a mapped state. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfMapNamedBuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pMapNamedBuffer(not_a_buffer_name, GL_READ_ONLY); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBuffer", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test access flag error behavior. */ |
| { |
| /* Prepare for invalid type error behavior verification. */ |
| static const glw::GLenum valid_access_flags[] = { GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE, GL_NONE }; |
| static const glw::GLenum valid_access_flags_last = |
| sizeof(valid_access_flags) / sizeof(valid_access_flags[0]) - 1; |
| |
| glw::GLenum invalid_access_flags = 0; |
| |
| while (&valid_access_flags[valid_access_flags_last] != |
| std::find(&valid_access_flags[0], &valid_access_flags[valid_access_flags_last], |
| (++invalid_access_flags))) |
| ; |
| |
| /* Test. */ |
| glw::GLbyte* mapped_data = (glw::GLbyte*)m_pMapNamedBuffer(buffer, invalid_access_flags); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBuffer", GL_INVALID_ENUM, |
| " if access is not READ_ONLY, WRITE_ONLY, or READ_WRITE."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test mapping of mapped buffer error behavior. */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBuffer(buffer, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer."); |
| |
| glw::GLbyte* subsequent_mapped_data = (glw::GLbyte*)m_pMapNamedBuffer(buffer, GL_READ_ONLY); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBuffer", GL_INVALID_OPERATION, |
| " if the buffer object is in a mapped state."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| if (subsequent_mapped_data) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glMapNamedBuffer called on mapped buffer returned non-NULL pointer when error shall occure." |
| "This may lead to undefined behavior during next tests (object still may be mapped). " |
| "Test was terminated prematurely." |
| << tcu::TestLog::EndMessage; |
| throw 0; |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of MapNamedBufferRange function. |
| * |
| * Check that INVALID_OPERATION is generated by MapNamedBufferRange if |
| * buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_VALUE is generated by MapNamedBufferRange if offset |
| * or length is negative, if offset+length is greater than the value of |
| * BUFFER_SIZE for the buffer object, or if access has any bits set other |
| * than those defined above. |
| * |
| * Check that INVALID_OPERATION is generated by MapNamedBufferRange for any |
| * of the following conditions: |
| * - length is zero. |
| * - The buffer object is already in a mapped state. |
| * - Neither MAP_READ_BIT nor MAP_WRITE_BIT is set. |
| * - MAP_READ_BIT is set and any of MAP_INVALIDATE_RANGE_BIT, |
| * MAP_INVALIDATE_BUFFER_BIT or MAP_UNSYNCHRONIZED_BIT is set. |
| * - MAP_FLUSH_EXPLICIT_BIT is set and MAP_WRITE_BIT is not set. |
| * - Any of MAP_READ_BIT, MAP_WRITE_BIT, MAP_PERSISTENT_BIT, or |
| * MAP_COHERENT_BIT are set, but the same bit is not included in the |
| * buffer's storage flags. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfMapNamedBufferRange() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLuint buffer_special_flags = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pMapNamedBufferRange(not_a_buffer_name, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test negative offset error behavior. */ |
| { |
| glw::GLvoid* mapped_data = m_pMapNamedBufferRange(buffer, -1, sizeof(dummy_data), GL_MAP_READ_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_VALUE, " if offset is negative."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test negative length error behavior. */ |
| { |
| glw::GLvoid* mapped_data = m_pMapNamedBufferRange(buffer, 0, -1, GL_MAP_READ_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_VALUE, " if length is negative."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test length overflow error behavior. */ |
| { |
| glw::GLvoid* mapped_data = m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data) * 2, GL_MAP_READ_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_VALUE, |
| " if length is greater than the value of BUFFER_SIZE" |
| " for the buffer object, or if access has any bits set other" |
| " than those defined above."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test (offset+length) overflow error behavior. */ |
| { |
| glw::GLvoid* mapped_data = |
| m_pMapNamedBufferRange(buffer, sizeof(dummy_data) / 2, sizeof(dummy_data), GL_MAP_READ_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_VALUE, |
| " if offset+length is greater than the value of BUFFER_SIZE" |
| " for the buffer object, or if access has any bits set other" |
| " than those defined above."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test zero length error behavior. */ |
| { |
| glw::GLvoid* mapped_data = m_pMapNamedBufferRange(buffer, 0, 0, GL_MAP_READ_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_OPERATION, " if length is zero."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test mapping of mapped buffer error behavior. */ |
| { |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer."); |
| |
| glw::GLvoid* subsequent_mapped_data = |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_OPERATION, |
| " if the buffer object is in a mapped state."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| |
| if (subsequent_mapped_data) |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "glMapNamedBufferRange called on mapped buffer returned non-NULL pointer when error shall " |
| "occure." |
| "This may lead to undefined behavior during next tests (object still may be mapped). " |
| "Test was terminated prematurely." |
| << tcu::TestLog::EndMessage; |
| throw 0; |
| } |
| } |
| |
| /* Test access flag read and write bits are not set error behavior. */ |
| { |
| glw::GLvoid* mapped_data = m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), 0); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_OPERATION, |
| " if neither MAP_READ_BIT nor MAP_WRITE_BIT is set."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test read access invalid flags error behavior. */ |
| { |
| glw::GLenum read_access_invalid_flags[] = { GL_MAP_INVALIDATE_RANGE_BIT, GL_MAP_INVALIDATE_BUFFER_BIT, |
| GL_MAP_UNSYNCHRONIZED_BIT }; |
| const glw::GLchar* read_access_invalid_flags_log[] = { |
| " if MAP_READ_BIT is set with MAP_INVALIDATE_RANGE_BIT.", |
| " if MAP_READ_BIT is set with MAP_INVALIDATE_BUFFER_BIT.", |
| " if MAP_READ_BIT is set with MAP_UNSYNCHRONIZED_BIT." |
| }; |
| glw::GLuint read_access_invalid_flags_count = |
| sizeof(read_access_invalid_flags) / sizeof(read_access_invalid_flags[0]); |
| |
| for (glw::GLuint i = 0; i < read_access_invalid_flags_count; ++i) |
| { |
| glw::GLvoid* mapped_data = m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), |
| GL_MAP_READ_BIT | read_access_invalid_flags[i]); |
| |
| is_ok &= |
| ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_OPERATION, read_access_invalid_flags_log[i]); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| } |
| |
| /* Test access flush bit without write bit error behavior. */ |
| { |
| glw::GLvoid* mapped_data = |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_OPERATION, |
| " if MAP_FLUSH_EXPLICIT_BIT is set and MAP_WRITE_BIT is not set."); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| } |
| |
| /* Test incompatible buffer flag error behavior. */ |
| { |
| glw::GLenum buffer_flags[] = { GL_MAP_WRITE_BIT, GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, |
| GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT }; |
| glw::GLenum mapping_flags[] = { GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT, |
| GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT }; |
| const glw::GLchar* mapping_flags_log[] = { |
| " if MAP_READ_BIT is set, but the same bit is not included in the buffer's storage flags.", |
| " if MAP_WRITE_BIT is set, but the same bit is not included in the buffer's storage flags.", |
| " if MAP_PERSISTENT_BIT is set, but the same bit is not included in the buffer's storage flags.", |
| " if MAP_COHERENT_BIT is set, but the same bit is not included in the buffer's storage flags." |
| }; |
| glw::GLuint flags_count = sizeof(mapping_flags) / sizeof(mapping_flags[0]); |
| |
| for (glw::GLuint i = 0; i < flags_count; ++i) |
| { |
| /* Create buffer. */ |
| gl.createBuffers(1, &buffer_special_flags); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer_special_flags, sizeof(dummy_data), &dummy_data, buffer_flags[i]); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test mapping. */ |
| glw::GLvoid* mapped_data = |
| m_pMapNamedBufferRange(buffer_special_flags, 0, sizeof(dummy_data), mapping_flags[i]); |
| |
| is_ok &= ErrorCheckAndLog("glMapNamedBufferRange", GL_INVALID_OPERATION, mapping_flags_log[i]); |
| |
| /* Sanity unmapping. */ |
| if (DE_NULL != mapped_data) |
| { |
| m_pUnmapNamedBuffer(buffer); |
| while (gl.getError()) |
| ; |
| } |
| |
| /* Releasing buffer. */ |
| if (buffer_special_flags) |
| { |
| gl.deleteBuffers(1, &buffer_special_flags); |
| |
| buffer_special_flags = 0; |
| } |
| } |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (buffer_special_flags) |
| { |
| gl.deleteBuffers(1, &buffer_special_flags); |
| |
| buffer_special_flags = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of NamedBufferData function. |
| * |
| * Check that INVALID_OPERATION is generated by NamedBufferData if buffer |
| * is not the name of an existing buffer object. |
| * |
| * Check that INVALID_ENUM is generated by NamedBufferData if usage is not |
| * STREAM_DRAW, STREAM_READ, STREAM_COPY, STATIC_DRAW, STATIC_READ, |
| * STATIC_COPY, DYNAMIC_DRAW, DYNAMIC_READ or DYNAMIC_COPY. |
| * |
| * Check that INVALID_VALUE is generated by NamedBufferData if size is |
| * negative. |
| * |
| * Check that INVALID_OPERATION is generated by NamedBufferData if the |
| * BUFFER_IMMUTABLE_STORAGE flag of the buffer object is TRUE. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfNamedBufferData() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLuint immutable_buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| std::stack<glw::GLuint> too_much_buffers; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| gl.createBuffers(1, &immutable_buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(immutable_buffer, sizeof(dummy_data), &dummy_data, GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pNamedBufferData(not_a_buffer_name, sizeof(dummy_data), dummy_data, GL_DYNAMIC_COPY); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferData", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test invalid usage error behavior. */ |
| { |
| /* Prepare for invalid type error behavior verification. */ |
| static const glw::GLenum valid_usages[] = { GL_STREAM_DRAW, GL_STREAM_READ, GL_STREAM_COPY, |
| GL_STATIC_DRAW, GL_STATIC_READ, GL_STATIC_COPY, |
| GL_DYNAMIC_DRAW, GL_DYNAMIC_READ, GL_DYNAMIC_COPY, |
| GL_NONE }; |
| static const glw::GLenum valid_usages_last = sizeof(valid_usages) / sizeof(valid_usages[0]) - 1; |
| |
| glw::GLenum invalid_usage = 0; |
| |
| while (&valid_usages[valid_usages_last] != |
| std::find(&valid_usages[0], &valid_usages[valid_usages_last], (++invalid_usage))) |
| ; |
| |
| /* Test. */ |
| m_pNamedBufferData(buffer, sizeof(dummy_data), dummy_data, invalid_usage); |
| |
| is_ok &= |
| ErrorCheckAndLog("glNamedBufferData", GL_INVALID_ENUM, |
| " if usage is not STREAM_DRAW, STREAM_READ, STREAM_COPY, STATIC_DRAW, STATIC_READ," |
| " STATIC_COPY, DYNAMIC_DRAW, DYNAMIC_READ or DYNAMIC_COPY."); |
| } |
| |
| /* Test negative size error behavior. */ |
| { |
| m_pNamedBufferData(buffer, -1, dummy_data, GL_DYNAMIC_COPY); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferData", GL_INVALID_VALUE, " if size is negative."); |
| } |
| |
| /* Test immutable buffer error behavior. */ |
| { |
| m_pNamedBufferData(immutable_buffer, sizeof(dummy_data) / 2, dummy_data, GL_DYNAMIC_COPY); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferData", GL_INVALID_OPERATION, |
| " if the BUFFER_IMMUTABLE_STORAGE flag of the buffer object is TRUE."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| while (!too_much_buffers.empty()) |
| { |
| glw::GLuint tmp_buffer = too_much_buffers.top(); |
| |
| if (tmp_buffer) |
| { |
| gl.deleteBuffers(1, &tmp_buffer); |
| } |
| |
| too_much_buffers.pop(); |
| } |
| |
| if (immutable_buffer) |
| { |
| gl.deleteBuffers(1, &immutable_buffer); |
| |
| immutable_buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of NamedBufferStorage function. |
| * |
| * Check that INVALID_OPERATION is generated by NamedBufferStorage if |
| * buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_VALUE is generated by NamedBufferStorage if size is |
| * less than or equal to zero. |
| * |
| * Check that INVALID_VALUE is generated by NamedBufferStorage if flags has |
| * any bits set other than DYNAMIC_STORAGE_BIT, MAP_READ_BIT, |
| * MAP_WRITE_BIT, MAP_PERSISTENT_BIT, MAP_COHERENT_BIT or |
| * CLIENT_STORAGE_BIT. |
| * |
| * Check that INVALID_VALUE error is generated by NamedBufferStorage if |
| * flags contains MAP_PERSISTENT_BIT but does not contain at least one of |
| * MAP_READ_BIT or MAP_WRITE_BIT. |
| * |
| * Check that INVALID_VALUE is generated by NamedBufferStorage if flags |
| * contains MAP_COHERENT_BIT, but does not also contain MAP_PERSISTENT_BIT. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfNamedBufferStorage() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| std::stack<glw::GLuint> too_much_buffers; |
| |
| try |
| { |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pNamedBufferStorage(not_a_buffer_name, sizeof(dummy_data), dummy_data, GL_MAP_WRITE_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferStorage", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test negative or zero size error behavior. */ |
| { |
| /* Object creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Test negative size. */ |
| m_pNamedBufferStorage(buffer, -1, dummy_data, GL_DYNAMIC_COPY); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferStorage", GL_INVALID_VALUE, " if size is negative."); |
| |
| /* Test zero size. */ |
| m_pNamedBufferStorage(buffer, 0, dummy_data, GL_DYNAMIC_COPY); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferStorage", GL_INVALID_VALUE, " if size zero."); |
| |
| /* Clean-up. */ |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed."); |
| } |
| |
| /* Test invalid usage bit error behavior. */ |
| { |
| /* Prepare for invalid type error behavior verification. */ |
| glw::GLuint valid_bits = GL_DYNAMIC_STORAGE_BIT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | |
| GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_CLIENT_STORAGE_BIT; |
| |
| if (m_context.getContextInfo().isExtensionSupported("GL_ARB_sparse_buffer")) |
| { |
| valid_bits |= GL_SPARSE_STORAGE_BIT_ARB; |
| } |
| |
| if (m_context.getContextInfo().isExtensionSupported("GL_NV_gpu_multicast") || |
| m_context.getContextInfo().isExtensionSupported("GL_NVX_linked_gpu_multicast")) |
| { |
| valid_bits |= GL_PER_GPU_STORAGE_BIT_NV; |
| } |
| |
| if (m_context.getContextInfo().isExtensionSupported("GL_NVX_cross_process_interop")) |
| { |
| valid_bits |= GL_EXTERNAL_STORAGE_BIT_NVX; |
| } |
| |
| glw::GLuint invalid_bits = ~valid_bits; |
| |
| glw::GLuint bits_count = CHAR_BIT * sizeof(invalid_bits); |
| |
| /* Test. */ |
| for (glw::GLuint i = 0; i < bits_count; ++i) |
| { |
| glw::GLuint possibly_invalid_bit = (1 << i); |
| |
| if (invalid_bits & possibly_invalid_bit) |
| { |
| /* Object creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Test invalid bit. */ |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), dummy_data, possibly_invalid_bit); |
| |
| is_ok &= |
| ErrorCheckAndLog("glNamedBufferStorage", GL_INVALID_VALUE, |
| " if flags has any bits set other than DYNAMIC_STORAGE_BIT, MAP_READ_BIT," |
| " MAP_WRITE_BIT, MAP_PERSISTENT_BIT, MAP_COHERENT_BIT or CLIENT_STORAGE_BIT."); |
| |
| /* Release object. */ |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed."); |
| } |
| } |
| } |
| |
| /* Test improper persistent bit behavior error behavior. */ |
| { |
| /* Object creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Test. */ |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), dummy_data, GL_MAP_PERSISTENT_BIT); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferStorage", GL_INVALID_VALUE, " if flags contains MAP_PERSISTENT_BIT " |
| "but does not contain at least one of " |
| "MAP_READ_BIT or MAP_WRITE_BIT."); |
| |
| /* Clean-up. */ |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed."); |
| } |
| |
| /* Test improper persistent bit behavior error behavior. */ |
| { |
| /* Object creation. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| /* Test. */ |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT); |
| |
| is_ok &= |
| ErrorCheckAndLog("glNamedBufferStorage", GL_INVALID_VALUE, |
| " if flags contains MAP_COHERENT_BIT, but does not also contain MAP_PERSISTENT_BIT."); |
| |
| /* Clean-up. */ |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers failed."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| while (!too_much_buffers.empty()) |
| { |
| glw::GLuint tmp_buffer = too_much_buffers.top(); |
| |
| if (tmp_buffer) |
| { |
| gl.deleteBuffers(1, &tmp_buffer); |
| } |
| |
| too_much_buffers.pop(); |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of NamedBufferSubData function. |
| * |
| * Check that INVALID_OPERATION is generated by NamedBufferSubData if |
| * buffer is not the name of an existing buffer object. |
| * |
| * Check that INVALID_VALUE is generated by NamedBufferSubData if offset or |
| * size is negative, or if offset+size is greater than the value of |
| * BUFFER_SIZE for the specified buffer object. |
| * |
| * Check that INVALID_OPERATION is generated by NamedBufferSubData if any |
| * part of the specified range of the buffer object is mapped with |
| * MapBufferRange or MapBuffer, unless it was mapped with the |
| * MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags. |
| * |
| * Check that INVALID_OPERATION is generated by NamedBufferSubData if the |
| * value of the BUFFER_IMMUTABLE_STORAGE flag of the buffer object is TRUE |
| * and the value of BUFFER_STORAGE_FLAGS for the buffer object does not |
| * have the DYNAMIC_STORAGE_BIT bit set. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfNamedBufferSubData() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLuint immutable_storage_buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| gl.createBuffers(1, &immutable_storage_buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(immutable_storage_buffer, sizeof(dummy_data), &dummy_data, GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pNamedBufferSubData(not_a_buffer_name, 0, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test negative offset error behavior. */ |
| { |
| /* Test. */ |
| m_pNamedBufferSubData(buffer, -1, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_INVALID_VALUE, " if offset or size is negative."); |
| } |
| |
| /* Test negative size error behavior. */ |
| { |
| /* Test. */ |
| m_pNamedBufferSubData(buffer, 0, -1, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_INVALID_VALUE, " if offset or size is negative."); |
| } |
| |
| /* Test size overflow error behavior. */ |
| { |
| /* Test. */ |
| m_pNamedBufferSubData(buffer, 0, sizeof(dummy_data) * 2, &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glNamedBufferSubData", GL_INVALID_VALUE, |
| " if offset+size is greater than the value of BUFFER_SIZE for the specified buffer object."); |
| } |
| |
| /* Test offset+size overflow error behavior. */ |
| { |
| /* Test. */ |
| m_pNamedBufferSubData(buffer, sizeof(dummy_data) / 2, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog( |
| "glNamedBufferSubData", GL_INVALID_VALUE, |
| " if offset+size is greater than the value of BUFFER_SIZE for the specified buffer object."); |
| } |
| |
| /* Test of mapped buffer subdata error behavior verification (with glMapBuffer). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBuffer(buffer, GL_READ_ONLY); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pNamedBufferSubData(buffer, 0, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_INVALID_OPERATION, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBuffer, unless it was mapped with " |
| "the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of mapped buffer subdata error behavior verification (with glMapBufferRange). */ |
| { |
| (void)(glw::GLbyte*) m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pNamedBufferSubData(buffer, 0, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_INVALID_OPERATION, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBufferRange, unless it was mapped with " |
| "the MAP_PERSISTENT_BIT bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test of persistently mapped buffer clear error with behavior verification. */ |
| { |
| (void)(glw::GLbyte*) |
| m_pMapNamedBufferRange(buffer, 0, sizeof(dummy_data), GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glMapNamedBuffer failed."); |
| |
| m_pNamedBufferSubData(buffer, 0, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_NO_ERROR, |
| " if any part of the specified range of the buffer" |
| " object is mapped with MapBuffer with the MAP_PERSISTENT_BIT" |
| " bit set in the MapBufferRange access flags."); |
| |
| m_pUnmapNamedBuffer(buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapNamedBuffer failed."); |
| } |
| |
| /* Test DYNAMIC_STORAGE_BIT bit off immutable buffer not set error behavior. */ |
| { |
| /* Test. */ |
| m_pNamedBufferSubData(immutable_storage_buffer, 0, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_INVALID_OPERATION, |
| " if the value of the BUFFER_IMMUTABLE_STORAGE flag of the buffer object is TRUE" |
| " and the value of BUFFER_STORAGE_FLAGS for the buffer object does not" |
| " have the DYNAMIC_STORAGE_BIT bit set."); |
| } |
| |
| /* Test DYNAMIC_STORAGE_BIT bit off immutable buffer set no error behavior. */ |
| { |
| /* Test. */ |
| m_pNamedBufferSubData(buffer, 0, sizeof(dummy_data), &dummy_data); |
| |
| is_ok &= ErrorCheckAndLog("glNamedBufferSubData", GL_NO_ERROR, |
| " if the value of the BUFFER_IMMUTABLE_STORAGE flag of the buffer object is TRUE" |
| " and the value of BUFFER_STORAGE_FLAGS for the buffer object" |
| " have the DYNAMIC_STORAGE_BIT bit set."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (immutable_storage_buffer) |
| { |
| gl.deleteBuffers(1, &immutable_storage_buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /** @brief Test Errors Of UnmapNamedBuffer function. |
| * |
| * Check that INVALID_OPERATION is generated by UnmapNamedBuffer if buffer |
| * is not the name of an existing buffer object. |
| * |
| * Check that INVALID_OPERATION is generated by UnmapNamedBuffer if the |
| * buffer object is not in a mapped state. |
| * |
| * True if test case succeeded, false otherwise. |
| */ |
| bool ErrorsTest::TestErrorsOfUnmapNamedBuffer() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Return value. */ |
| bool is_ok = true; |
| bool internal_error = false; |
| |
| /* Common variables. */ |
| glw::GLuint buffer = 0; |
| glw::GLubyte dummy_data[4] = {}; |
| |
| try |
| { |
| /* Common preparations. */ |
| gl.createBuffers(1, &buffer); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers failed."); |
| |
| m_pNamedBufferStorage(buffer, sizeof(dummy_data), &dummy_data, |
| GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glNamedBuffeStorage failed."); |
| |
| /* Test invalid buffer name error behavior. */ |
| { |
| /* Prepare for invalid buffer name error behavior verification. */ |
| glw::GLuint not_a_buffer_name = 0; |
| |
| while (gl.isBuffer(++not_a_buffer_name)) |
| ; |
| |
| /* Test. */ |
| m_pUnmapNamedBuffer(not_a_buffer_name); |
| |
| is_ok &= ErrorCheckAndLog("glUnmapNamedBuffer", GL_INVALID_OPERATION, |
| " if buffer is not the name of an existing buffer object."); |
| } |
| |
| /* Test not mapped buffer error behavior verification. */ |
| { |
| m_pUnmapNamedBuffer(buffer); |
| |
| is_ok &= ErrorCheckAndLog("glUnmapNamedBuffer", GL_INVALID_OPERATION, |
| " if the buffer object is not in a mapped state."); |
| } |
| } |
| catch (...) |
| { |
| is_ok = false; |
| internal_error = true; |
| } |
| |
| if (buffer) |
| { |
| gl.deleteBuffers(1, &buffer); |
| |
| buffer = 0; |
| } |
| |
| if (internal_error) |
| { |
| throw 0; |
| } |
| |
| return is_ok; |
| } |
| |
| /******************************** Functional Test Implementation ********************************/ |
| |
| /** @brief Vertex shader source code */ |
| const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 450\n" |
| "\n" |
| "in int data_in;\n" |
| "out int data_out;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n" |
| "\n" |
| " data_out = data_in * data_in;\n" |
| "}\n"; |
| |
| /** @brief Fragment shader source code */ |
| const glw::GLchar FunctionalTest::s_fragment_shader[] = "#version 450\n" |
| "\n" |
| "out vec4 color;\n" |
| "\n" |
| "void main()\n" |
| "{\n" |
| " color = vec4(0.0);\n" |
| "}\n"; |
| |
| const glw::GLchar FunctionalTest::s_vertex_shader_input_name[] = |
| "data_in"; //!< Vertex shader's name of the input attribute. |
| |
| const glw::GLchar* FunctionalTest::s_vertex_shader_output_name = |
| "data_out"; //!< Vertex shader's name of the transform feedback varying. |
| |
| const glw::GLint FunctionalTest::s_initial_data_a[] = { |
| 1, 2, 3, 4, 5, 5 |
| }; //!< Initial data to be uploaded for the input buffer. |
| |
| const glw::GLint FunctionalTest::s_initial_data_b[] = { |
| 0, 0, 0, 0, 0, 0, 36 |
| }; //!< Initial data to be uploaded for the output buffer. |
| |
| const glw::GLint FunctionalTest::s_expected_data[] = { |
| 0, 1, 4, 9, 16, 25, 36 |
| }; //!< Expected result which shall be read from output buffer. |
| |
| /** @brief Functional Test constructor. |
| * |
| * @param [in] context OpenGL context. |
| */ |
| FunctionalTest::FunctionalTest(deqp::Context& context) |
| : deqp::TestCase(context, "buffers_functional", "Buffer Objects Functional Test") |
| , m_pClearNamedBufferData(DE_NULL) |
| , m_pClearNamedBufferSubData(DE_NULL) |
| , m_pCopyNamedBufferSubData(DE_NULL) |
| , m_pFlushMappedNamedBufferRange(DE_NULL) |
| , m_pGetNamedBufferParameteri64v(DE_NULL) |
| , m_pGetNamedBufferParameteriv(DE_NULL) |
| , m_pGetNamedBufferPointerv(DE_NULL) |
| , m_pGetNamedBufferSubData(DE_NULL) |
| , m_pMapNamedBuffer(DE_NULL) |
| , m_pMapNamedBufferRange(DE_NULL) |
| , m_pNamedBufferData(DE_NULL) |
| , m_pNamedBufferStorage(DE_NULL) |
| , m_pNamedBufferSubData(DE_NULL) |
| , m_pUnmapNamedBuffer(DE_NULL) |
| , m_po(0) |
| , m_vao(0) |
| , m_bo_in(0) |
| , m_bo_out(0) |
| , m_attrib_location(-1) |
| { |
| /* Intentionally left blank. */ |
| } |
| |
| /** @brief Run Functional Test. |
| * |
| * @return Iteration result. |
| */ |
| tcu::TestNode::IterateResult FunctionalTest::iterate() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Get context setup. */ |
| bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); |
| bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); |
| |
| if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); |
| |
| return STOP; |
| } |
| |
| /* Running tests. */ |
| bool is_ok = true; |
| bool is_error = false; |
| |
| /* API function pointers setup. */ |
| m_pClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATA)gl.clearNamedBufferData; |
| m_pClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATA)gl.clearNamedBufferSubData; |
| m_pCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATA)gl.copyNamedBufferSubData; |
| m_pFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGE)gl.flushMappedNamedBufferRange; |
| m_pGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64V)gl.getNamedBufferParameteri64v; |
| m_pGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIV)gl.getNamedBufferParameteriv; |
| m_pGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERV)gl.getNamedBufferPointerv; |
| m_pGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATA)gl.getNamedBufferSubData; |
| m_pMapNamedBuffer = (PFNGLMAPNAMEDBUFFER)gl.mapNamedBuffer; |
| m_pMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGE)gl.mapNamedBufferRange; |
| m_pNamedBufferData = (PFNGLNAMEDBUFFERDATA)gl.namedBufferData; |
| m_pNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGE)gl.namedBufferStorage; |
| m_pNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATA)gl.namedBufferSubData; |
| m_pUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFER)gl.unmapNamedBuffer; |
| |
| try |
| { |
| /* API function pointers check. */ |
| if ((DE_NULL == m_pClearNamedBufferData) || (DE_NULL == m_pClearNamedBufferSubData) || |
| (DE_NULL == m_pCopyNamedBufferSubData) || (DE_NULL == m_pFlushMappedNamedBufferRange) || |
| (DE_NULL == m_pGetNamedBufferParameteri64v) || (DE_NULL == m_pGetNamedBufferParameteriv) || |
| (DE_NULL == m_pGetNamedBufferPointerv) || (DE_NULL == m_pGetNamedBufferSubData) || |
| (DE_NULL == m_pMapNamedBuffer) || (DE_NULL == m_pMapNamedBufferRange) || (DE_NULL == m_pNamedBufferData) || |
| (DE_NULL == m_pNamedBufferStorage) || (DE_NULL == m_pNamedBufferSubData) || |
| (DE_NULL == m_pUnmapNamedBuffer)) |
| { |
| throw 0; |
| } |
| |
| /* Running test. */ |
| BuildProgram(); |
| PrepareVertexArrayObject(); |
| |
| is_ok = is_ok && PrepareInputBuffer(); |
| is_ok = is_ok && PrepareOutputBuffer(); |
| |
| if (is_ok) |
| { |
| Draw(); |
| } |
| |
| is_ok = is_ok && CheckArrayBufferImmutableFlag(); |
| is_ok = is_ok && CheckTransformFeedbackBufferSize(); |
| is_ok = is_ok && CheckTransformFeedbackResult(); |
| } |
| catch (...) |
| { |
| is_ok = false; |
| is_error = true; |
| } |
| |
| /* Clean Up. */ |
| Cleanup(); |
| |
| /* Errors clean up. */ |
| while (gl.getError()) |
| ; |
| |
| /* Result's setup. */ |
| if (is_ok) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| } |
| else |
| { |
| if (is_error) |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); |
| } |
| else |
| { |
| m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); |
| } |
| } |
| |
| return STOP; |
| } |
| |
| /** @brief Build test's GL program */ |
| void FunctionalTest::BuildProgram() |
| { |
| /* Shortcut for GL functionality */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| struct Shader |
| { |
| glw::GLchar const* const source; |
| glw::GLenum const type; |
| glw::GLuint id; |
| } shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } }; |
| |
| glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]); |
| |
| try |
| { |
| /* Create program. */ |
| m_po = gl.createProgram(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed."); |
| |
| /* Shader compilation. */ |
| |
| for (glw::GLuint i = 0; i < shader_count; ++i) |
| { |
| if (DE_NULL != shader[i].source) |
| { |
| shader[i].id = gl.createShader(shader[i].type); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed."); |
| |
| gl.attachShader(m_po, shader[i].id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed."); |
| |
| gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed."); |
| |
| gl.compileShader(shader[i].id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed."); |
| |
| glw::GLint status = GL_FALSE; |
| |
| gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); |
| |
| if (GL_FALSE == status) |
| { |
| glw::GLint log_size = 0; |
| gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed."); |
| |
| glw::GLchar* log_text = new glw::GLchar[log_size]; |
| |
| gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]); |
| |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n" |
| << "Shader type: " << glu::getShaderTypeStr(shader[i].type) |
| << "\n" |
| << "Shader compilation error log:\n" |
| << log_text << "\n" |
| << "Shader source code:\n" |
| << shader[i].source << "\n" |
| << tcu::TestLog::EndMessage; |
| |
| delete[] log_text; |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed."); |
| |
| throw 0; |
| } |
| } |
| } |
| |
| /* Tranform feedback varying */ |
| gl.transformFeedbackVaryings(m_po, 1, &s_vertex_shader_output_name, GL_INTERLEAVED_ATTRIBS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed."); |
| |
| /* Link. */ |
| gl.linkProgram(m_po); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram call failed."); |
| |
| glw::GLint status = GL_FALSE; |
| |
| gl.getProgramiv(m_po, GL_LINK_STATUS, &status); |
| |
| if (GL_TRUE == status) |
| { |
| for (glw::GLuint i = 0; i < shader_count; ++i) |
| { |
| if (shader[i].id) |
| { |
| gl.detachShader(m_po, shader[i].id); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed."); |
| } |
| } |
| } |
| else |
| { |
| glw::GLint log_size = 0; |
| |
| gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size); |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); |
| |
| glw::GLchar* log_text = new glw::GLchar[log_size]; |
| |
| gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]); |
| |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n" |
| << log_text << "\n" |
| << tcu::TestLog::EndMessage; |
| |
| delete[] log_text; |
| |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed."); |
| |
| throw 0; |
| } |
| } |
| catch (...) |
| { |
| if (m_po) |
| { |
| gl.deleteProgram(m_po); |
| |
| m_po = 0; |
| } |
| } |
| |
| for (glw::GLuint i = 0; i < shader_count; ++i) |
| { |
| if (0 != shader[i].id) |
| { |
| gl.deleteShader(shader[i].id); |
| |
| shader[i].id = 0; |
| } |
| } |
| |
| if (m_po) |
| { |
| gl.useProgram(m_po); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed."); |
| } |
| |
| if (0 == m_po) |
| { |
| throw 0; |
| } |
| } |
| |
| /** @brief Prepare empty vertex array object and bind it. */ |
| void FunctionalTest::PrepareVertexArrayObject() |
| { |
| /* Shortcut for GL functionality */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| gl.genVertexArrays(1, &m_vao); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); |
| |
| gl.bindVertexArray(m_vao); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); |
| } |
| |
| /** Prepare input buffer in the way described in test specification (see class comment). */ |
| bool FunctionalTest::PrepareInputBuffer() |
| { |
| /* Shortcut for GL functionality */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Constants. */ |
| static const glw::GLint zero = 0; |
| static const glw::GLint one = 1; |
| |
| /* Buffer preparation */ |
| gl.createBuffers(1, &m_bo_in); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Storage and last (6th) element preparation. */ |
| m_pNamedBufferStorage(m_bo_in, sizeof(s_initial_data_a), s_initial_data_a, |
| GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT | GL_MAP_PERSISTENT_BIT); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* First element preparation. */ |
| m_pClearNamedBufferSubData(m_bo_in, GL_R8, 0, sizeof(glw::GLint), GL_RED, GL_INT, &zero); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Second element preparation. */ |
| m_pNamedBufferSubData(m_bo_in, 1 /* 2nd element */ * sizeof(glw::GLint), sizeof(glw::GLint), &one); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Third element preparation. */ |
| glw::GLint* p = (glw::GLint*)m_pMapNamedBuffer(m_bo_in, GL_WRITE_ONLY); |
| |
| if ((GL_NO_ERROR == gl.getError()) || (DE_NULL == p)) |
| { |
| p[2] = 2; |
| |
| m_pUnmapNamedBuffer(m_bo_in); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Fifth element preparation. */ |
| m_pCopyNamedBufferSubData(m_bo_in, m_bo_in, sizeof(glw::GLint) * 3, sizeof(glw::GLint) * 4, |
| sizeof(glw::GLint)); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Fourth element preparation. */ |
| p = (glw::GLint*)m_pMapNamedBufferRange( |
| m_bo_in, sizeof(glw::GLint) * 3, sizeof(glw::GLint), |
| GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_FLUSH_EXPLICIT_BIT); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Write to mapped buffer. */ |
| *p = 3; |
| |
| /* Flush test. */ |
| m_pFlushMappedNamedBufferRange(m_bo_in, 0, sizeof(glw::GLint)); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Mapped Buffer Pointer query. */ |
| glw::GLvoid* is_p = DE_NULL; |
| m_pGetNamedBufferPointerv(m_bo_in, GL_BUFFER_MAP_POINTER, &is_p); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Mapped Buffer pointer query check. */ |
| if (p == is_p) |
| { |
| /* Unmapping. */ |
| m_pUnmapNamedBuffer(m_bo_in); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Setup buffer as input for vertex shader. */ |
| m_attrib_location = |
| gl.getAttribLocation(m_po, s_vertex_shader_input_name); |
| GLU_EXPECT_NO_ERROR(gl.getError(), |
| "glGetAttribLocation call failed."); |
| |
| gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_in); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed."); |
| |
| gl.vertexAttribIPointer(m_attrib_location, 1, GL_INT, 0, NULL); |
| GLU_EXPECT_NO_ERROR(gl.getError(), |
| "glVertexAttribIPointer call failed."); |
| |
| gl.enableVertexAttribArray(m_attrib_location); |
| GLU_EXPECT_NO_ERROR(gl.getError(), |
| "glEnableVertexAttribArray call failed."); |
| |
| return true; |
| } |
| else |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "UnmapNamedBuffer has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_pUnmapNamedBuffer(m_bo_in); |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message |
| << "Pointer returned by GetNamedBufferPointerv is not proper." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_pUnmapNamedBuffer(m_bo_in); |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "GetNamedBufferPointerv has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_pUnmapNamedBuffer(m_bo_in); |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "FlushMappedNamedBufferRange has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "MapNamedBufferRange has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "CopyNamedBufferSubData has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() |
| << tcu::TestLog::Message << "UnmapNamedBuffer has failed." << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "MapNamedBuffer has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "NamedBufferSubData has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "ClearNamedBufferSubData has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "NamedBufferStorage has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "CreateBuffers has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| |
| return false; |
| } |
| |
| /** Prepare output buffer in the way described in test specification (see class comment). */ |
| bool FunctionalTest::PrepareOutputBuffer() |
| { |
| /* Shortcut for GL functionality */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Buffer preparation */ |
| gl.genBuffers(1, &m_bo_out); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_out); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| m_pNamedBufferData(m_bo_out, sizeof(s_initial_data_b), s_initial_data_b, GL_DYNAMIC_COPY); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_out, 0, |
| sizeof(s_initial_data_a) /* intentionally sizeof(a) < sizeof(b) */); |
| |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| return true; |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "BindBufferRange has failed." |
| << tcu::TestLog::EndMessage; |
| throw 0; /* This function is not being tested, throw test internal error */ |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "NamedBufferData has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "BindBuffer has failed." |
| << tcu::TestLog::EndMessage; |
| throw 0; /* This function is not being tested, throw test internal error */ |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GenBuffers has failed." |
| << tcu::TestLog::EndMessage; |
| throw 0; /* This function is not being tested, throw test internal error */ |
| } |
| |
| return false; |
| } |
| |
| /** Draw with the test program and transform feedback. */ |
| void FunctionalTest::Draw() |
| { |
| /* Shortcut for GL functionality */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Draw using transform feedback. */ |
| gl.disable(GL_RASTERIZER_DISCARD); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed."); |
| |
| gl.beginTransformFeedback(GL_POINTS); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed."); |
| |
| gl.drawArrays(GL_POINTS, 0, sizeof(s_initial_data_a) / sizeof(s_initial_data_a[0])); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed."); |
| |
| gl.endTransformFeedback(); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed."); |
| |
| gl.enable(GL_RASTERIZER_DISCARD); |
| GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed."); |
| } |
| |
| /** @brief Check that input buffer is immutable using GetNamedBufferParameteriv function. */ |
| bool FunctionalTest::CheckArrayBufferImmutableFlag() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Local query storage. */ |
| glw::GLint is_storage_immutable = -1; |
| |
| /* Querry. */ |
| m_pGetNamedBufferParameteriv(m_bo_in, GL_BUFFER_IMMUTABLE_STORAGE, &is_storage_immutable); |
| |
| /* Error checking. */ |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Return value checking. */ |
| if (-1 != is_storage_immutable) |
| { |
| /* Test. */ |
| if (GL_TRUE == is_storage_immutable) |
| { |
| return true; |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "Input buffer storage is unexpectedly mutable." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "GetNamedBufferParameteriv has not returned a data." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetNamedBufferParameteriv has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| |
| return false; |
| } |
| |
| /** @brief Check that output buffer size using GetNamedBufferParameteri64v function. */ |
| bool FunctionalTest::CheckTransformFeedbackBufferSize() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Local query storage. */ |
| glw::GLint64 size = -1; |
| |
| /* Querry. */ |
| m_pGetNamedBufferParameteri64v(m_bo_out, GL_BUFFER_SIZE, &size); |
| |
| /* Error checking. */ |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| /* Return value checking. */ |
| if (-1 != size) |
| { |
| /* Test. */ |
| if (sizeof(s_initial_data_b) == size) |
| { |
| return true; |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Output buffer size is " << size |
| << ", but " << sizeof(s_initial_data_b) << " was expected." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message |
| << "GetNamedBufferParameteri64v has not returned a data." |
| << tcu::TestLog::EndMessage; |
| } |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetNamedBufferParameteri64v has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| |
| return false; |
| } |
| |
| /** @brief Check that results of the test are equal to the expected reference values. */ |
| bool FunctionalTest::CheckTransformFeedbackResult() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Local data storage. */ |
| glw::GLint output_data[sizeof(s_initial_data_b) / sizeof(s_initial_data_b[0])] = {}; |
| |
| /* Fetch data. */ |
| m_pGetNamedBufferSubData(m_bo_out, 0, sizeof(output_data), output_data); |
| |
| /* Error checking. */ |
| if (GL_NO_ERROR == gl.getError()) |
| { |
| for (glw::GLuint i = 0; i < sizeof(s_initial_data_b) / sizeof(s_initial_data_b[0]); ++i) |
| { |
| if (s_expected_data[i] != output_data[i]) |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "Expected data is not equal to results." |
| << tcu::TestLog::EndMessage; |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| else |
| { |
| m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetNamedBufferSubData has failed." |
| << tcu::TestLog::EndMessage; |
| } |
| return false; |
| } |
| |
| /** Clean all test's GL objects and state. */ |
| void FunctionalTest::Cleanup() |
| { |
| /* Shortcut for GL functionality. */ |
| const glw::Functions& gl = m_context.getRenderContext().getFunctions(); |
| |
| /* Cleanup objects. */ |
| if (m_po) |
| { |
| gl.useProgram(0); |
| |
| gl.deleteProgram(m_po); |
| |
| m_po = 0; |
| } |
| |
| if (m_vao) |
| { |
| gl.deleteVertexArrays(1, &m_vao); |
| |
| m_vao = 0; |
| } |
| |
| if (0 <= m_attrib_location) |
| { |
| gl.disableVertexAttribArray(m_attrib_location); |
| |
| m_attrib_location = -1; |
| } |
| |
| if (m_bo_in) |
| { |
| gl.deleteBuffers(1, &m_bo_in); |
| |
| m_bo_in = 0; |
| } |
| |
| if (m_bo_out) |
| { |
| gl.deleteBuffers(1, &m_bo_out); |
| |
| m_bo_out = 0; |
| } |
| |
| /* Make sure that rasterizer is turned on (default). */ |
| gl.enable(GL_RASTERIZER_DISCARD); |
| |
| /* Clean all errors. */ |
| while (gl.getError()) |
| ; |
| } |
| |
| } /* Buffers namespace. */ |
| } /* DirectStateAccess namespace. */ |
| } /* gl4cts namespace. */ |