| /*------------------------------------------------------------------------- |
| * 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); |
|