| /*------------------------------------------------------------------------- |
| * OpenGL Conformance Test Suite |
| * ----------------------------- |
| * |
| * Copyright (c) 2015-2018 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 glcKHRDebugTests.cpp |
| * \brief Implements conformance tests for "KHR Debug" functionality. |
| */ /*-------------------------------------------------------------------*/ |
| |
| #include "glcKHRDebugTests.hpp" |
| |
| #include "gluPlatform.hpp" |
| #include "gluRenderConfig.hpp" |
| #include "gluRenderContext.hpp" |
| #include "gluStrUtil.hpp" |
| #include "glwEnums.hpp" |
| #include "glwFunctions.hpp" |
| #include "tcuCommandLine.hpp" |
| #include "tcuTestLog.hpp" |
| // |
| //#include <string> |
| |
| #define DEBUG_ENBALE_MESSAGE_CALLBACK 0 |
| |
| #if DEBUG_ENBALE_MESSAGE_CALLBACK |
| //#include <iomanip> |
| #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */ |
| |
| using namespace glw; |
| |
| namespace glcts |
| { |
| namespace KHRDebug |
| { |
| /** Macro, verifies generated error, logs error message and throws failure |
| * |
| * @param expected_error Expected error value |
| * @param error_message Message logged if generated error is not the expected one |
| **/ |
| #define CHECK_ERROR(expected_error, error_message) \ |
| do { \ |
| GLenum generated_error = m_gl->getError(); \ |
| \ |
| if (expected_error != generated_error) \ |
| { \ |
| m_testCtx.getLog() \ |
| << tcu::TestLog::Message << "File: " << __FILE__ << ", line: " << __LINE__ \ |
| << ". Got wrong error: " << glu::getErrorStr(generated_error) \ |
| << ", expected: " << glu::getErrorStr(expected_error) << ", message: " << error_message \ |
| << tcu::TestLog::EndMessage; \ |
| TestBase::done(); \ |
| TCU_FAIL("Invalid error generated"); \ |
| } \ |
| } while (0) |
| |
| /** Pop all groups from stack |
| * |
| * @param gl GL functions |
| **/ |
| void cleanGroupStack(const Functions* gl) |
| { |
| while (1) |
| { |
| gl->popDebugGroup(); |
| |
| const GLenum err = gl->getError(); |
| |
| if (GL_STACK_UNDERFLOW == err) |
| { |
| break; |
| } |
| |
| GLU_EXPECT_NO_ERROR(err, "PopDebugGroup"); |
| } |
| } |
| |
| /** Extracts all messages from log |
| * |
| * @param gl GL functions |
| **/ |
| void cleanMessageLog(const Functions* gl) |
| { |
| static const GLuint count = 16; |
| |
| while (1) |
| { |
| GLuint ret = gl->getDebugMessageLog(count /* count */, 0 /* bufSize */, 0 /* sources */, 0 /* types */, |
| 0 /* ids */, 0 /* severities */, 0 /* lengths */, 0 /* messageLog */); |
| |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GetDebugMessageLog"); |
| |
| if (0 == ret) |
| { |
| break; |
| } |
| } |
| } |
| |
| /** Fill stack of groups |
| * |
| * @param gl GL functions |
| **/ |
| void fillGroupStack(const Functions* gl) |
| { |
| static const GLchar message[] = "Foo"; |
| static const GLsizei length = (GLsizei)(sizeof(message) / sizeof(message[0])); |
| |
| while (1) |
| { |
| gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */, |
| message /* message */); |
| |
| const GLenum err = gl->getError(); |
| |
| if (GL_STACK_OVERFLOW == err) |
| { |
| break; |
| } |
| |
| GLU_EXPECT_NO_ERROR(err, "PopDebugGroup"); |
| } |
| } |
| |
| /** Constructor |
| * Creates and set as current new context that should be used by test. |
| * |
| * @param testCtx Test context |
| * @param is_debug Selects if debug or non-debug context should be created |
| **/ |
| TestBase::TestBase(tcu::TestContext& testContext, glu::ApiType apiType, bool is_debug) |
| : m_gl(0), m_is_debug(is_debug), m_rc(0), m_testContext(testContext), m_apiType(apiType) |
| { |
| /* Nothing to be done here */ |
| } |
| |
| /** Destructor |
| * Destroys context used by test and set original context as current |
| **/ |
| TestBase::~TestBase() |
| { |
| if (0 != m_rc) |
| { |
| done(); |
| } |
| } |
| |
| /** Initialize rendering context |
| **/ |
| void TestBase::init() |
| { |
| if (true == m_is_debug) |
| { |
| initDebug(); |
| } |
| else |
| { |
| initNonDebug(); |
| } |
| |
| /* Get functions */ |
| m_gl = &m_rc->getFunctions(); |
| } |
| |
| /** Prepares debug context |
| **/ |
| void TestBase::initDebug() |
| { |
| tcu::Platform& platform = m_testContext.getPlatform(); |
| glu::RenderConfig renderCfg(glu::ContextType(m_apiType, glu::CONTEXT_DEBUG)); |
| |
| const tcu::CommandLine& commandLine = m_testContext.getCommandLine(); |
| parseRenderConfig(&renderCfg, commandLine); |
| |
| if (commandLine.getSurfaceType() != tcu::SURFACETYPE_WINDOW) |
| throw tcu::NotSupportedError("Test not supported in non-windowed context"); |
| |
| m_rc = createRenderContext(platform, commandLine, renderCfg); |
| m_rc->makeCurrent(); |
| } |
| |
| /** Prepares non-debug context |
| **/ |
| void TestBase::initNonDebug() |
| { |
| tcu::Platform& platform = m_testContext.getPlatform(); |
| glu::RenderConfig renderCfg(glu::ContextType(m_apiType, glu::ContextFlags(0))); |
| |
| const tcu::CommandLine& commandLine = m_testContext.getCommandLine(); |
| parseRenderConfig(&renderCfg, commandLine); |
| |
| if (commandLine.getSurfaceType() != tcu::SURFACETYPE_WINDOW) |
| throw tcu::NotSupportedError("Test not supported in non-windowed context"); |
| |
| m_rc = createRenderContext(platform, commandLine, renderCfg); |
| m_rc->makeCurrent(); |
| } |
| |
| /** Finalize rendering context |
| **/ |
| void TestBase::done() |
| { |
| /* Delete context used by test and make no context current */ |
| delete m_rc; |
| |
| m_rc = 0; |
| m_gl = 0; |
| } |
| |
| /** Constructor |
| * |
| * @param testCtx Test context |
| * @param is_debug Selects if debug or non-debug context should be used |
| * @param name Name of test |
| **/ |
| APIErrorsTest::APIErrorsTest(tcu::TestContext& testCtx, glu::ApiType apiType, bool is_debug, const GLchar* name) |
| : TestBase(testCtx, apiType, is_debug), TestCase(testCtx, name, "Verifies that errors are generated as expected") |
| { |
| /* Nothing to be done */ |
| } |
| |
| /** Execute test |
| * |
| * @return tcu::TestNode::STOP |
| **/ |
| tcu::TestNode::IterateResult APIErrorsTest::iterate() |
| { |
| /* Initialize rendering context */ |
| TestBase::init(); |
| |
| /* Get maximum label length */ |
| GLint max_label = 0; |
| |
| m_gl->getIntegerv(GL_MAX_LABEL_LENGTH, &max_label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| /* Prepare too long label */ |
| std::vector<GLchar> too_long_label; |
| |
| too_long_label.resize(max_label + 2); |
| |
| for (GLint i = 0; i <= max_label; ++i) |
| { |
| too_long_label[i] = 'f'; |
| } |
| |
| too_long_label[max_label + 1] = 0; |
| |
| /* Get maximum message length */ |
| GLint max_length = 0; |
| |
| m_gl->getIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &max_length); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| /* Prepare too long message */ |
| std::vector<GLchar> too_long_message; |
| |
| too_long_message.resize(max_length + 2); |
| |
| for (GLint i = 0; i <= max_length; ++i) |
| { |
| too_long_message[i] = 'f'; |
| } |
| |
| too_long_message[max_length + 1] = 0; |
| |
| /* Get maximum number of groups on stack */ |
| GLint max_groups = 0; |
| |
| m_gl->getIntegerv(GL_MAX_DEBUG_GROUP_STACK_DEPTH, &max_groups); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| /* |
| * DebugMessageControl function should generate: |
| * - INVALID_ENUM when <source> is invalid; |
| * - INVALID_ENUM when <type> is invalid; |
| * - INVALID_ENUM when <severity> is invalid; |
| * - INVALID_VALUE when <count> is negative; |
| * - INVALID_OPERATION when <count> is not zero and <source> is DONT_CARE; |
| * - INVALID_OPERATION when <count> is not zero and <type> is DONT_CARE; |
| * - INVALID_OPERATION when <count> is not zero and <severity> is not |
| * DONT_CARE. |
| */ |
| { |
| static const GLuint ids[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; |
| static const GLsizei n_ids = (GLsizei)(sizeof(ids) / sizeof(ids[0])); |
| |
| m_gl->debugMessageControl(GL_ARRAY_BUFFER /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_DEBUG_SEVERITY_LOW /* severity */, 0 /* count */, 0 /* ids */, |
| GL_TRUE /* enabled */); |
| CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <source> set to GL_ARRAY_BUFFER"); |
| |
| m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_ARRAY_BUFFER /* type */, |
| GL_DEBUG_SEVERITY_LOW /* severity */, 0 /* count */, 0 /* ids */, |
| GL_TRUE /* enabled */); |
| CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <type> set to GL_ARRAY_BUFFER"); |
| |
| m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_ARRAY_BUFFER /* severity */, 0 /* count */, 0 /* ids */, GL_TRUE /* enabled */); |
| CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageControl with <severity> set to GL_ARRAY_BUFFER"); |
| |
| m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_DEBUG_SEVERITY_LOW /* severity */, -1 /* count */, ids /* ids */, |
| GL_TRUE /* enabled */); |
| CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageControl with <count> set to -1"); |
| |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_DONT_CARE /* severity */, n_ids /* count */, ids /* ids */, GL_TRUE /* enabled */); |
| CHECK_ERROR(GL_INVALID_OPERATION, "DebugMessageControl with <source> set to GL_DONT_CARE and non zero <count>"); |
| |
| m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DONT_CARE /* type */, |
| GL_DONT_CARE /* severity */, n_ids /* count */, ids /* ids */, GL_TRUE /* enabled */); |
| CHECK_ERROR(GL_INVALID_OPERATION, "DebugMessageControl with <type> set to GL_DONT_CARE and non zero <count>"); |
| |
| m_gl->debugMessageControl(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_DEBUG_SEVERITY_LOW /* severity */, n_ids /* count */, ids /* ids */, |
| GL_TRUE /* enabled */); |
| CHECK_ERROR(GL_INVALID_OPERATION, |
| "DebugMessageControl with <severity> set to GL_DEBUG_SEVERITY_LOW and non zero <count>"); |
| } |
| |
| /* |
| * GetDebugMessageLog function should generate: |
| * - INVALID_VALUE when <bufSize> is negative and messageLog is not NULL. |
| */ |
| { |
| static const GLsizei bufSize = 32; |
| static const GLuint count = 4; |
| |
| GLenum ids[count]; |
| GLsizei lengths[count]; |
| GLchar messageLog[bufSize]; |
| GLenum types[count]; |
| GLenum severities[count]; |
| GLenum sources[count]; |
| |
| m_gl->getDebugMessageLog(count /* count */, -1 /* bufSize */, sources, types, ids, severities, lengths, |
| messageLog); |
| CHECK_ERROR(GL_INVALID_VALUE, "GetDebugMessageLog with <bufSize> set to -1"); |
| } |
| |
| /* |
| * DebugMessageInsert function should generate: |
| * - INVALID_ENUM when <source> is not DEBUG_SOURCE_APPLICATION or |
| * DEBUG_SOURCE_THIRD_PARTY; |
| * - INVALID_ENUM when <type> is invalid; |
| * - INVALID_ENUM when <severity> is invalid; |
| * - INVALID_VALUE when length of string <buf> is not less than |
| * MAX_DEBUG_MESSAGE_LENGTH. |
| */ |
| { |
| static const GLchar message[] = "Foo"; |
| static const GLsizei length = (GLsizei)(sizeof(message) / sizeof(message[0])); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_API /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */, |
| 0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, length /* length */, |
| message /* message */); |
| CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <source> set to GL_DEBUG_SOURCE_API"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_ARRAY_BUFFER /* type */, 0 /* id */, |
| GL_DEBUG_SEVERITY_LOW /* severity */, length /* length */, message /* message */); |
| CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <type> set to GL_ARRAY_BUFFER"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */, |
| 0 /* id */, GL_ARRAY_BUFFER /* severity */, length /* length */, |
| message /* message */); |
| CHECK_ERROR(GL_INVALID_ENUM, "DebugMessageInsert with <severity> set to GL_ARRAY_BUFFER"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */, |
| 0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, max_length + 1 /* length */, |
| message /* message */); |
| CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageInsert with <length> set to GL_MAX_DEBUG_MESSAGE_LENGTH + 1"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR /* type */, |
| 0 /* id */, GL_DEBUG_SEVERITY_LOW /* severity */, -1 /* length */, |
| &too_long_message[0] /* message */); |
| CHECK_ERROR(GL_INVALID_VALUE, "DebugMessageInsert with too long message"); |
| } |
| |
| /* |
| * PushDebugGroup function should generate: |
| * - INVALID_ENUM when <source> is not DEBUG_SOURCE_APPLICATION or |
| * DEBUG_SOURCE_THIRD_PARTY; |
| * - INVALID_VALUE when length of string <message> is not less than |
| * MAX_DEBUG_MESSAGE_LENGTH; |
| * - STACK_OVERFLOW when stack contains MAX_DEBUG_GROUP_STACK_DEPTH entries. |
| */ |
| { |
| static const GLchar message[] = "Foo"; |
| static const GLsizei length = (GLsizei)(sizeof(message) / sizeof(message[0])); |
| |
| m_gl->pushDebugGroup(GL_DEBUG_SOURCE_API /* source */, 1 /* id */, length /* length */, message /* message */); |
| CHECK_ERROR(GL_INVALID_ENUM, "PushDebugGroup with <source> set to GL_DEBUG_SOURCE_API"); |
| |
| m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, max_length + 1 /* length */, |
| message /* message */); |
| CHECK_ERROR(GL_INVALID_VALUE, "PushDebugGroup with <length> set to GL_MAX_DEBUG_MESSAGE_LENGTH + 1"); |
| |
| m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, -1 /* length */, |
| &too_long_message[0] /* message */); |
| CHECK_ERROR(GL_INVALID_VALUE, "PushDebugGroup with too long message"); |
| |
| /* Clean stack */ |
| cleanGroupStack(m_gl); |
| |
| /* Fill stack */ |
| for (GLint i = 0; i < max_groups - 1; ++i) |
| { |
| m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */, |
| message /* message */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup"); |
| } |
| |
| /* Overflow stack */ |
| m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 1 /* id */, length /* length */, |
| message /* message */); |
| CHECK_ERROR(GL_STACK_OVERFLOW, "PushDebugGroup called GL_MAX_DEBUG_GROUP_STACK_DEPTH times"); |
| |
| /* Clean stack */ |
| cleanGroupStack(m_gl); |
| } |
| |
| /* |
| * PopDebugGroup function should generate: |
| * - STACK_UNDERFLOW when stack contains no entries. |
| */ |
| { |
| fillGroupStack(m_gl); |
| |
| for (GLint i = 0; i < max_groups - 1; ++i) |
| { |
| m_gl->popDebugGroup(); |
| |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup"); |
| } |
| |
| m_gl->popDebugGroup(); |
| CHECK_ERROR(GL_STACK_UNDERFLOW, "PopDebugGroup called GL_MAX_DEBUG_GROUP_STACK_DEPTH times"); |
| } |
| |
| /* |
| * ObjectLabel function should generate: |
| * - INVALID_ENUM when <identifier> is invalid; |
| * - INVALID_VALUE when if <name> is not valid object name of type specified by |
| * <identifier>; |
| * - INVALID_VALUE when length of string <label> is not less than |
| * MAX_LABEL_LENGTH. |
| */ |
| { |
| static const GLchar label[] = "Foo"; |
| static const GLsizei length = (GLsizei)(sizeof(label) / sizeof(label[0])); |
| |
| GLuint texture_id = 0; |
| GLuint invalid_id = 1; |
| m_gl->genTextures(1, &texture_id); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenTextures"); |
| m_gl->bindTexture(GL_TEXTURE_BUFFER, texture_id); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "BindTexture"); |
| |
| try |
| { |
| m_gl->objectLabel(GL_TEXTURE_BUFFER /* identifier */, texture_id /* name */, length /* length */, |
| label /* label */); |
| CHECK_ERROR(GL_INVALID_ENUM, "ObjectLabel with <identifier> set to GL_TEXTURE_BUFFER"); |
| |
| while (GL_TRUE == m_gl->isTexture(invalid_id)) |
| { |
| invalid_id += 1; |
| } |
| |
| m_gl->objectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, length /* length */, |
| label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with <name> set to not generated value"); |
| |
| m_gl->objectLabel(GL_TEXTURE /* identifier */, texture_id /* name */, max_label + 1 /* length */, |
| label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with <label> set to MAX_LABEL_LENGTH + 1"); |
| |
| m_gl->objectLabel(GL_TEXTURE /* identifier */, texture_id /* name */, -1 /* length */, |
| &too_long_label[0] /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "ObjectLabel with too long label"); |
| } |
| catch (const std::exception& exc) |
| { |
| m_gl->deleteTextures(1, &texture_id); |
| TCU_FAIL(exc.what()); |
| } |
| |
| m_gl->deleteTextures(1, &texture_id); |
| } |
| |
| /* |
| * GetObjectLabel function should generate: |
| * - INVALID_ENUM when <identifier> is invalid; |
| * - INVALID_VALUE when if <name> is not valid object name of type specified by |
| * <identifier>; |
| * - INVALID_VALUE when <bufSize> is negative. |
| */ |
| { |
| static const GLsizei bufSize = 32; |
| |
| GLchar label[bufSize]; |
| GLsizei length = 0; |
| |
| GLuint texture_id = 0; |
| GLuint invalid_id = 1; |
| m_gl->genTextures(1, &texture_id); |
| m_gl->bindTexture(GL_TEXTURE_2D, texture_id); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenTextures"); |
| |
| try |
| { |
| m_gl->getObjectLabel(GL_TEXTURE_BUFFER /* identifier */, texture_id /* name */, bufSize /* bufSize */, |
| &length /* length */, label /* label */); |
| CHECK_ERROR(GL_INVALID_ENUM, "GetObjectLabel with <identifier> set to GL_TEXTURE_BUFFER"); |
| |
| while (GL_TRUE == m_gl->isTexture(invalid_id)) |
| { |
| invalid_id += 1; |
| } |
| |
| m_gl->getObjectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, bufSize /* bufSize */, |
| &length /* length */, label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "GetObjectLabel with <name> set to not generated value"); |
| |
| m_gl->getObjectLabel(GL_TEXTURE /* identifier */, invalid_id /* name */, -1 /* bufSize */, |
| &length /* length */, label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "GetObjectLabel with <bufSize> set to -1"); |
| } |
| catch (const std::exception& exc) |
| { |
| m_gl->deleteTextures(1, &texture_id); |
| TCU_FAIL(exc.what()); |
| } |
| |
| m_gl->deleteTextures(1, &texture_id); |
| } |
| |
| /* |
| * ObjectPtrLabel function should generate: |
| * - INVALID_VALUE when <ptr> is not the name of sync object; |
| * - INVALID_VALUE when length of string <label> is not less than |
| * MAX_LABEL_LENGTH. |
| */ |
| { |
| static const GLchar label[] = "Foo"; |
| static const GLsizei length = (GLsizei)(sizeof(label) / sizeof(label[0])); |
| |
| GLsync sync_id = 0; |
| GLsync invalid_id = 0; |
| sync_id = m_gl->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "FenceSync"); |
| |
| try |
| { |
| while (GL_TRUE == m_gl->isSync(invalid_id)) |
| { |
| invalid_id = (GLsync)(((unsigned long long)invalid_id) + 1); |
| } |
| |
| m_gl->objectPtrLabel(invalid_id /* name */, length /* length */, label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with <ptr> set to not generated value"); |
| |
| m_gl->objectPtrLabel(sync_id /* name */, max_label + 1 /* length */, label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with <length> set to MAX_LABEL_LENGTH + 1"); |
| |
| m_gl->objectPtrLabel(sync_id /* name */, -1 /* length */, &too_long_label[0] /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "ObjectPtrLabel with too long label"); |
| } |
| catch (const std::exception& exc) |
| { |
| m_gl->deleteSync(sync_id); |
| TCU_FAIL(exc.what()); |
| } |
| |
| m_gl->deleteSync(sync_id); |
| } |
| |
| /* |
| * GetObjectPtrLabel function should generate: |
| * - INVALID_VALUE when <ptr> is not the name of sync object; |
| * - INVALID_VALUE when <bufSize> is negative. |
| */ |
| { |
| static const GLsizei bufSize = 32; |
| |
| GLchar label[bufSize]; |
| GLsizei length = 0; |
| |
| GLsync sync_id = 0; |
| GLsync invalid_id = 0; |
| sync_id = m_gl->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "FenceSync"); |
| |
| try |
| { |
| while (GL_TRUE == m_gl->isSync(invalid_id)) |
| { |
| invalid_id = (GLsync)(((unsigned long long)invalid_id) + 1); |
| } |
| |
| m_gl->getObjectPtrLabel(invalid_id /* name */, bufSize /* bufSize */, &length /* length */, |
| label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "GetObjectPtrLabel with <ptr> set to not generated value"); |
| |
| m_gl->getObjectPtrLabel(sync_id /* name */, -1 /* bufSize */, &length /* length */, label /* label */); |
| CHECK_ERROR(GL_INVALID_VALUE, "GetObjectPtrLabel with <bufSize> set to -1"); |
| } |
| catch (const std::exception& exc) |
| { |
| m_gl->deleteSync(sync_id); |
| TCU_FAIL(exc.what()); |
| } |
| |
| m_gl->deleteSync(sync_id); |
| } |
| |
| /* |
| * GetPointerv function should generate: |
| * - INVALID_ENUM when <pname> is invalid. |
| **/ |
| { |
| GLuint uint; |
| GLuint* uint_ptr = &uint; |
| |
| m_gl->getPointerv(GL_ARRAY_BUFFER, (GLvoid**)&uint_ptr); |
| CHECK_ERROR(GL_INVALID_ENUM, "GetPointerv with <pname> set to GL_ARRAY_BUFFER"); |
| } |
| |
| /* Set result */ |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| |
| /* Done */ |
| TestBase::done(); |
| |
| return tcu::TestNode::STOP; |
| } |
| |
| /** Constructor |
| * |
| * @param testCtx Test context |
| * @param is_debug Selects if debug or non-debug context should be used |
| * @param name Name of test |
| **/ |
| LabelsTest::LabelsTest(tcu::TestContext& testCtx, glu::ApiType apiType, bool is_debug, const GLchar* name) |
| : TestCase(testCtx, name, "Verifies that labels can be assigned and queried"), TestBase(testCtx, apiType, is_debug) |
| { |
| /* Nothing to be done */ |
| } |
| |
| /** Represnets case for LabelsTest **/ |
| struct labelsTestCase |
| { |
| GLenum m_identifier; |
| GLuint (*m_create)(const glw::Functions* gl, const glu::RenderContext*); |
| GLvoid (*m_destroy)(const glw::Functions* gl, GLuint id); |
| const GLchar* m_name; |
| }; |
| |
| /** Execute test |
| * |
| * @return tcu::TestNode::STOP |
| **/ |
| tcu::TestNode::IterateResult LabelsTest::iterate() |
| { |
| static const labelsTestCase test_cases[] = { |
| { GL_BUFFER, createBuffer, deleteBuffer, "Buffer" }, |
| { GL_FRAMEBUFFER, createFramebuffer, deleteFramebuffer, "Framebuffer" }, |
| { GL_PROGRAM, createProgram, deleteProgram, "Program" }, |
| { GL_PROGRAM_PIPELINE, createProgramPipeline, deleteProgramPipeline, "ProgramPipeline" }, |
| { GL_QUERY, createQuery, deleteQuery, "Query" }, |
| { GL_RENDERBUFFER, createRenderbuffer, deleteRenderbuffer, "Renderbuffer" }, |
| { GL_SAMPLER, createSampler, deleteSampler, "Sampler" }, |
| { GL_SHADER, createShader, deleteShader, "Shader" }, |
| { GL_TEXTURE, createTexture, deleteTexture, "Texture" }, |
| { GL_TRANSFORM_FEEDBACK, createTransformFeedback, deleteTransformFeedback, "TransformFeedback" }, |
| { GL_VERTEX_ARRAY, createVertexArray, deleteVertexArray, "VertexArray" }, |
| }; |
| |
| static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]); |
| |
| static const GLsizei bufSize = 32; |
| static const GLchar label[] = "foo"; |
| static const GLsizei label_length = (GLsizei)(sizeof(label) / sizeof(label[0]) - 1); |
| |
| /* Initialize render context */ |
| TestBase::init(); |
| |
| /* For each test case */ |
| for (size_t test_case_index = 0; test_case_index < n_test_cases; ++test_case_index) |
| { |
| const labelsTestCase& test_case = test_cases[test_case_index]; |
| |
| const GLenum identifier = test_case.m_identifier; |
| const GLuint id = test_case.m_create(m_gl, m_rc); |
| |
| try |
| { |
| GLchar buffer[bufSize] = "HelloWorld"; |
| GLsizei length; |
| |
| /* |
| * - query label; It is expected that result will be an empty string and length |
| * will be zero; |
| */ |
| m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel"); |
| |
| if (0 != length) |
| { |
| TCU_FAIL("Just created object has label of length != 0"); |
| } |
| |
| if (0 != buffer[0]) |
| { |
| TCU_FAIL("Just created object has not empty label"); |
| } |
| |
| /* |
| * - assign label to object; |
| * - query label; It is expected that result will be equal to the provided |
| * label and length will be correct; |
| */ |
| m_gl->objectLabel(identifier, id, -1 /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel"); |
| |
| m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel"); |
| |
| if (label_length != length) |
| { |
| TCU_FAIL("Length is different than length of set label"); |
| } |
| |
| if (0 != strcmp(buffer, label)) |
| { |
| TCU_FAIL("Different label returned"); |
| } |
| |
| /* |
| * - query length only; Correct value is expected; |
| */ |
| length = 0; |
| |
| m_gl->getObjectLabel(identifier, id, 0 /* bufSize */, &length, 0 /* label */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel"); |
| |
| if (label_length != length) |
| { |
| TCU_FAIL("Invalid length returned when label and bufSize are set to 0"); |
| } |
| |
| /* |
| * - query label with <bufSize> less than actual length of label; It is |
| * expected that only <bufSize> characters will be stored in buffer (including |
| * NULL); |
| */ |
| length = 0; |
| strcpy(buffer, "HelloWorld"); |
| |
| m_gl->getObjectLabel(identifier, id, 2 /* bufSize */, &length, buffer); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel"); |
| |
| if (buffer[0] != label[0]) |
| { |
| TCU_FAIL("Different label returned"); |
| } |
| |
| if (buffer[1] != 0) |
| { |
| TCU_FAIL("GetObjectLabel did not stored NULL at the end of string"); |
| } |
| |
| if (buffer[2] != 'l') |
| { |
| TCU_FAIL("GetObjectLabel overflowed buffer"); |
| } |
| |
| /* |
| * - query label with <bufSize> equal zero; It is expected that buffer contents |
| * will not be modified; |
| */ |
| length = 0; |
| strcpy(buffer, "HelloWorld"); |
| |
| m_gl->getObjectLabel(identifier, id, 0 /* bufSize */, &length, buffer); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel"); |
| |
| if (0 != strcmp(buffer, "HelloWorld")) |
| { |
| TCU_FAIL("GetObjectLabel modified buffer, bufSize set to 0"); |
| } |
| |
| /* |
| * - assign empty string as label to object; |
| * - query label, it is expected that result will be an empty string and length |
| * will be zero; |
| */ |
| m_gl->objectLabel(identifier, id, -1 /* length */, ""); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel"); |
| |
| m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel"); |
| |
| if (0 != length) |
| { |
| TCU_FAIL("Label length is != 0, empty string was set"); |
| } |
| |
| if (0 != buffer[0]) |
| { |
| TCU_FAIL("Non empty label returned, empty string was set"); |
| } |
| |
| /* |
| * - assign NULL as label to object; |
| * - query label, it is expected that result will be an empty string and length |
| * will be zero; |
| */ |
| m_gl->objectLabel(identifier, id, 2, 0 /* label */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "ObjectLabel"); |
| |
| m_gl->getObjectLabel(identifier, id, bufSize, &length, buffer); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetObjectLabel"); |
| |
| if (0 != length) |
| { |
| TCU_FAIL("Label length is != 0, label was removed"); |
| } |
| |
| if (0 != buffer[0]) |
| { |
| TCU_FAIL("Different label returned, label was removed"); |
| } |
| } |
| catch (const std::exception& exc) |
| { |
| test_case.m_destroy(m_gl, id); |
| |
| m_testCtx.getLog() |
| << tcu::TestLog::Message << "Error during test case: " << test_case.m_name << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL(exc.what()); |
| } |
| |
| test_case.m_destroy(m_gl, id); |
| } |
| |
| /* Set result */ |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| |
| /* Done */ |
| TestBase::done(); |
| |
| return tcu::TestNode::STOP; |
| } |
| |
| /** Create buffer |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createBuffer(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createBuffers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateBuffers"); |
| } |
| else |
| { |
| gl->genBuffers(1, &id); |
| gl->bindBuffer(GL_ARRAY_BUFFER, id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenBuffers"); |
| } |
| |
| return id; |
| } |
| |
| /** Create FBO |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createFramebuffer(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createFramebuffers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateFramebuffers"); |
| } |
| else |
| { |
| GLint currentFbo; |
| gl->getIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, ¤tFbo); |
| gl->genFramebuffers(1, &id); |
| gl->bindFramebuffer(GL_DRAW_FRAMEBUFFER, id); |
| gl->bindFramebuffer(GL_DRAW_FRAMEBUFFER, currentFbo); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenFramebuffers / BindFramebuffer"); |
| } |
| |
| return id; |
| } |
| |
| /** Create program |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createProgram(const Functions* gl, const glu::RenderContext*) |
| { |
| GLuint id = gl->createProgram(); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateProgram"); |
| |
| return id; |
| } |
| |
| /** Create pipeline |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createProgramPipeline(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createProgramPipelines(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateProgramPipelines"); |
| } |
| else |
| { |
| gl->genProgramPipelines(1, &id); |
| gl->bindProgramPipeline(id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenProgramPipelines / BindProgramPipeline"); |
| } |
| |
| return id; |
| } |
| |
| /** Create query |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createQuery(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createQueries(GL_TIMESTAMP, 1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateQueries"); |
| } |
| else |
| { |
| gl->genQueries(1, &id); |
| gl->beginQuery(GL_SAMPLES_PASSED, id); |
| gl->endQuery(GL_SAMPLES_PASSED); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenQueries / BeginQuery / EndQuery"); |
| } |
| |
| return id; |
| } |
| |
| /** Create render buffer |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createRenderbuffer(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createRenderbuffers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateRenderbuffers"); |
| } |
| else |
| { |
| gl->genRenderbuffers(1, &id); |
| gl->bindRenderbuffer(GL_RENDERBUFFER, id); |
| gl->bindRenderbuffer(GL_RENDERBUFFER, 0); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenRenderbuffers / BindRenderbuffer"); |
| } |
| |
| return id; |
| } |
| |
| /** Create sampler |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createSampler(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createSamplers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateSamplers"); |
| } |
| else |
| { |
| gl->genSamplers(1, &id); |
| gl->bindSampler(0, id); |
| gl->bindSampler(0, 0); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenSamplers / BindSampler"); |
| } |
| |
| return id; |
| } |
| |
| /** Create shader |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createShader(const Functions* gl, const glu::RenderContext*) |
| { |
| GLuint id = gl->createShader(GL_VERTEX_SHADER); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateShader"); |
| |
| return id; |
| } |
| |
| /** Create texture |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createTexture(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createTextures(GL_TEXTURE_2D, 1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateTextures"); |
| } |
| else |
| { |
| gl->genTextures(1, &id); |
| gl->bindTexture(GL_TEXTURE_2D, id); |
| gl->bindTexture(GL_TEXTURE_2D, 0); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenTextures / BindTexture"); |
| } |
| |
| return id; |
| } |
| |
| /** Create XFB |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createTransformFeedback(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createTransformFeedbacks(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateTransformFeedbacks"); |
| } |
| else |
| { |
| gl->genTransformFeedbacks(1, &id); |
| gl->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, id); |
| gl->bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenTransformFeedbacks / BindTransformFeedback"); |
| } |
| |
| return id; |
| } |
| |
| /** Create VAO |
| * |
| * @param gl GL functions |
| * |
| * @return ID of created resource |
| **/ |
| GLuint LabelsTest::createVertexArray(const Functions* gl, const glu::RenderContext* rc) |
| { |
| GLuint id = 0; |
| |
| if (glu::contextSupports(rc->getType(), glu::ApiType::core(4, 5))) |
| { |
| gl->createVertexArrays(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "CreateVertexArrays"); |
| } |
| else |
| { |
| gl->genVertexArrays(1, &id); |
| gl->bindVertexArray(id); |
| gl->bindVertexArray(0); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "GenVertexArrays / BindVertexArrays"); |
| } |
| |
| return id; |
| } |
| |
| /** Destroy buffer |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteBuffer(const Functions* gl, GLuint id) |
| { |
| gl->deleteBuffers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteBuffers"); |
| } |
| |
| /** Destroy FBO |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteFramebuffer(const Functions* gl, GLuint id) |
| { |
| gl->deleteFramebuffers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteFramebuffers"); |
| } |
| |
| /** Destroy program |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteProgram(const Functions* gl, GLuint id) |
| { |
| gl->deleteProgram(id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteProgram"); |
| } |
| |
| /** Destroy pipeline |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteProgramPipeline(const Functions* gl, GLuint id) |
| { |
| gl->deleteProgramPipelines(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteProgramPipelines"); |
| } |
| |
| /** Destroy query |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteQuery(const Functions* gl, GLuint id) |
| { |
| gl->deleteQueries(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteQueries"); |
| } |
| |
| /** Destroy render buffer |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteRenderbuffer(const Functions* gl, GLuint id) |
| { |
| gl->deleteRenderbuffers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteRenderbuffers"); |
| } |
| |
| /** Destroy sampler |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteSampler(const Functions* gl, GLuint id) |
| { |
| gl->deleteSamplers(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteSamplers"); |
| } |
| |
| /** Destroy shader |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteShader(const Functions* gl, GLuint id) |
| { |
| gl->deleteShader(id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteShader"); |
| } |
| |
| /** Destroy texture |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteTexture(const Functions* gl, GLuint id) |
| { |
| gl->deleteTextures(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteTextures"); |
| } |
| |
| /** Destroy XFB |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteTransformFeedback(const Functions* gl, GLuint id) |
| { |
| gl->deleteTransformFeedbacks(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteTransformFeedbacks"); |
| } |
| |
| /** Destroy VAO |
| * |
| * @param gl GL functions |
| * @param id ID of resource |
| **/ |
| GLvoid LabelsTest::deleteVertexArray(const Functions* gl, GLuint id) |
| { |
| gl->deleteVertexArrays(1, &id); |
| GLU_EXPECT_NO_ERROR(gl->getError(), "DeleteVertexArrays"); |
| } |
| |
| /** Constructor |
| * |
| * @param testCtx Test context |
| * @param is_debug Selects if debug or non-debug context should be used |
| * @param name Name of test |
| **/ |
| ReceivingMessagesTest::ReceivingMessagesTest(tcu::TestContext& testCtx, glu::ApiType apiType) |
| : TestCase(testCtx, "receiving_messages", "Verifies that messages can be received") |
| , TestBase(testCtx, apiType, true /* is_debug */) |
| { |
| /* Nothing to be done */ |
| } |
| |
| /** Execute test |
| * |
| * @return tcu::TestNode::STOP |
| **/ |
| tcu::TestNode::IterateResult ReceivingMessagesTest::iterate() |
| { |
| static const size_t bufSize = 32; |
| static const GLchar label[] = "foo"; |
| static const size_t label_length = sizeof(label) / sizeof(label[0]) - 1; |
| static const size_t read_messages = 4; |
| |
| GLuint callback_counter = 0; |
| GLint max_debug_messages = 0; |
| |
| /* Initialize render context */ |
| TestBase::init(); |
| |
| /* Get max number of debug messages */ |
| m_gl->getIntegerv(GL_MAX_DEBUG_LOGGED_MESSAGES, &max_debug_messages); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| /* |
| * - verify that the state of DEBUG_OUTPUT is enabled as it should be by |
| * default; |
| * - verify that state of DEBUG_CALLBACK_FUNCTION and |
| * DEBUG_CALLBACK_USER_PARAM are NULL; |
| */ |
| { |
| inspectDebugState(GL_TRUE, 0 /* cb */, 0 /* info */); |
| } |
| |
| /* |
| * Ignore spurious performance messages |
| */ |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_PERFORMANCE /* type */, |
| GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */); |
| |
| /* |
| * - insert a message with DebugMessageInsert; |
| * - inspect message log to check if the message is reported; |
| * - inspect message log again, there should be no messages; |
| */ |
| { |
| GLchar messageLog[bufSize]; |
| GLenum sources[read_messages]; |
| GLenum types[read_messages]; |
| GLuint ids[read_messages]; |
| GLenum severities[read_messages]; |
| GLsizei lengths[read_messages]; |
| |
| cleanMessageLog(m_gl); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, sources /* sources */, |
| types /* types */, ids /* ids */, severities /* severities */, |
| lengths /* lengths */, messageLog /* messageLog */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog"); |
| |
| if (1 != ret) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "GetDebugMessageLog returned invalid number of messages: " << ret |
| << ", expected 1" << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_SOURCE_APPLICATION != sources[0]) |
| { |
| TCU_FAIL("Invalid source value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_TYPE_ERROR != types[0]) |
| { |
| TCU_FAIL("Invalid type value returned by GetDebugMessageLog"); |
| } |
| |
| if (11 != ids[0]) |
| { |
| TCU_FAIL("Invalid id value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_SEVERITY_HIGH != severities[0]) |
| { |
| TCU_FAIL("Invalid severity value returned by GetDebugMessageLog"); |
| } |
| |
| // DebugMessageInsert's length does not include null-terminated character (if length is positive) |
| // But GetDebugMessageLog's length include null-terminated character |
| // OpenGL 4.5 Core Spec, Page 530 and Page 535 |
| if (label_length + 1 != lengths[0]) |
| { |
| TCU_FAIL("Invalid length value returned by GetDebugMessageLog"); |
| } |
| |
| if (0 != strcmp(label, messageLog)) |
| { |
| TCU_FAIL("Invalid message returned by GetDebugMessageLog"); |
| } |
| } |
| |
| /* |
| * - disable DEBUG_OUTPUT; |
| * - insert a message with DebugMessageInsert; |
| * - inspect message log again, there should be no messages; |
| */ |
| { |
| m_gl->disable(GL_DEBUG_OUTPUT); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Disable"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(0); |
| } |
| |
| /* |
| * - enable DEBUG_OUTPUT; |
| * - register debug message callback with DebugMessageCallback; |
| * - verify that the state of DEBUG_CALLBACK_FUNCTION and |
| * DEBUG_CALLBACK_USER_PARAM are correct; |
| * - insert a message with DebugMessageInsert; |
| * - it is expected that debug message callback will be executed for |
| * the message; |
| * - inspect message log to check there are no messages; |
| */ |
| { |
| m_gl->enable(GL_DEBUG_OUTPUT); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable"); |
| |
| m_gl->debugMessageCallback(debug_proc, &callback_counter); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageCallback"); |
| |
| inspectDebugState(GL_TRUE, debug_proc, &callback_counter); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectCallbackCounter(callback_counter, 1); |
| |
| inspectMessageLog(0); |
| } |
| |
| /* |
| * - disable DEBUG_OUTPUT; |
| * - insert a message with DebugMessageInsert; |
| * - debug message callback should not be called; |
| * - inspect message log to check there are no messages; |
| */ |
| { |
| m_gl->disable(GL_DEBUG_OUTPUT); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Disable"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectCallbackCounter(callback_counter, 1); |
| |
| inspectMessageLog(0); |
| } |
| |
| /* |
| * - enable DEBUG_OUTPUT; |
| * - execute DebugMessageControl with <type> DEBUG_TYPE_ERROR, <severity> |
| * DEBUG_SEVERITY_HIGH and <enabled> FALSE; |
| * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_ERROR |
| * and <severity> DEBUG_SEVERITY_MEDIUM; |
| * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER |
| * and <severity> DEBUG_SEVERITY_HIGH; |
| * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER |
| * and <severity> DEBUG_SEVERITY_LOW; |
| * - debug message callback should not be called; |
| * - inspect message log to check there are no messages; |
| */ |
| { |
| m_gl->enable(GL_DEBUG_OUTPUT); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable"); |
| |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */); |
| |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DONT_CARE /* type */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, 0 /* counts */, 0 /* ids */, |
| GL_FALSE /* enabled */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_LOW /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectCallbackCounter(callback_counter, 1); |
| |
| inspectMessageLog(0); |
| } |
| |
| /* |
| * - set NULL as debug message callback; |
| * - verify that state of DEBUG_CALLBACK_FUNCTION and |
| * DEBUG_CALLBACK_USER_PARAM are NULL; |
| * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_ERROR |
| * and <severity> DEBUG_SEVERITY_MEDIUM; |
| * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER |
| * and <severity> DEBUG_SEVERITY_HIGH; |
| * - insert a message with DebugMessageInsert, set <type> to DEBUG_TYPE_OTHER |
| * and <severity> DEBUG_SEVERITY_LOW; |
| * - inspect message log to check there are no messages; |
| */ |
| { |
| m_gl->debugMessageCallback(0, 0); |
| |
| inspectDebugState(GL_TRUE, 0, 0); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_LOW /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(0); |
| } |
| |
| /* |
| * - execute DebugMessageControl to enable messages of <type> DEBUG_TYPE_ERROR |
| * and <severity> DEBUG_SEVERITY_HIGH. |
| */ |
| { |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_TRUE /* enabled */); |
| |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DONT_CARE /* type */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, 0 /* counts */, 0 /* ids */, |
| GL_TRUE /* enabled */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl"); |
| } |
| |
| /* |
| * - insert MAX_DEBUG_LOGGED_MESSAGES + 1 unique messages with |
| * DebugMessageInsert; |
| * - check state of DEBUG_LOGGED_MESSAGES; It is expected that |
| * MAX_DEBUG_LOGGED_MESSAGES will be reported; |
| */ |
| { |
| for (GLint i = 0; i < max_debug_messages + 1; ++i) |
| { |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| i /* id */, GL_DEBUG_SEVERITY_MEDIUM /* severity */, label_length /* length */, |
| label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| } |
| |
| GLint n_debug_messages = 0; |
| |
| m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| if (n_debug_messages != max_debug_messages) |
| { |
| m_testCtx.getLog() |
| << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected " |
| << max_debug_messages << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES"); |
| } |
| } |
| |
| /* |
| * If MAX_DEBUG_LOGGED_MESSAGES is greater than 1: |
| * - inspect first half of the message log by specifying proper <count>; Verify |
| * that messages are reported in order from the oldest to the newest; Check |
| * that <count> messages were stored into provided buffers; |
| * - check state of DEBUG_LOGGED_MESSAGES; It is expected that <count> messages |
| * were removed from log; |
| * - inspect rest of the message log with <bufSize> too small to held last |
| * message; Verify that messages are reported in order from the oldest to the |
| * newest; Verify that maximum <bufSize> characters were written to |
| * <messageLog>; |
| * - check state of DEBUG_LOGGED_MESSAGES; It is expected that one message is |
| * available; |
| * - fetch the message and verify it is the newest one; |
| */ |
| if (1 != max_debug_messages) |
| { |
| GLint half_count = max_debug_messages / 2; |
| GLint n_debug_messages = 0; |
| GLint rest_count = max_debug_messages - half_count; |
| |
| GLsizei buf_size = (GLsizei)((half_count + 1) * (label_length + 1)); |
| |
| std::vector<GLchar> messageLog; |
| std::vector<GLenum> sources; |
| std::vector<GLenum> types; |
| std::vector<GLuint> ids; |
| std::vector<GLenum> severities; |
| std::vector<GLsizei> lengths; |
| |
| messageLog.resize(buf_size); |
| sources.resize(half_count + 1); |
| types.resize(half_count + 1); |
| ids.resize(half_count + 1); |
| severities.resize(half_count + 1); |
| lengths.resize(half_count + 1); |
| |
| GLuint ret = m_gl->getDebugMessageLog(half_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */, |
| &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */, |
| &lengths[0] /* lengths */, &messageLog[0] /* messageLog */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog"); |
| |
| if (ret != (GLuint)half_count) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "GetDebugMessageLog returned unexpected number of messages: " << ret |
| << ", expected " << half_count << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid number of meessages"); |
| } |
| |
| m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| if (n_debug_messages != rest_count) |
| { |
| m_testCtx.getLog() |
| << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected " |
| << rest_count << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES"); |
| } |
| |
| for (GLint i = 0; i < half_count; ++i) |
| { |
| if (GL_DEBUG_SOURCE_APPLICATION != sources[i]) |
| { |
| TCU_FAIL("Invalid source value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_TYPE_ERROR != types[i]) |
| { |
| TCU_FAIL("Invalid type value returned by GetDebugMessageLog"); |
| } |
| |
| if ((GLuint)i != ids[i]) |
| { |
| TCU_FAIL("Invalid id value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_SEVERITY_MEDIUM != severities[i]) |
| { |
| TCU_FAIL("Invalid severity value returned by GetDebugMessageLog"); |
| } |
| |
| // DebugMessageInsert's length does not include null-terminated character (if length is positive) |
| // But GetDebugMessageLog's length include null-terminated character |
| // OpenGL 4.5 Core Spec, Page 530 and Page 535 |
| if (label_length + 1 != lengths[i]) |
| { |
| TCU_FAIL("Invalid length value returned by GetDebugMessageLog"); |
| } |
| |
| if (0 != strcmp(label, &messageLog[i * (label_length + 1)])) |
| { |
| TCU_FAIL("Invalid message returned by GetDebugMessageLog"); |
| } |
| } |
| |
| /* */ |
| buf_size = (GLsizei)((rest_count - 1) * (label_length + 1) + label_length); |
| memset(&messageLog[0], 0, messageLog.size()); |
| |
| ret = m_gl->getDebugMessageLog(rest_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */, |
| &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */, |
| &lengths[0] /* lengths */, &messageLog[0] /* messageLog */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog"); |
| |
| if (ret != (GLuint)(rest_count - 1)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "GetDebugMessageLog returned unexpected number of messages: " << ret |
| << ", expected " << (rest_count - 1) << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid number of meessages"); |
| } |
| |
| m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| if (n_debug_messages != 1) |
| { |
| m_testCtx.getLog() |
| << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected " |
| << (rest_count - 1) << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES"); |
| } |
| |
| for (GLint i = 0; i < (rest_count - 1); ++i) |
| { |
| if (GL_DEBUG_SOURCE_APPLICATION != sources[i]) |
| { |
| TCU_FAIL("Invalid source value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_TYPE_ERROR != types[i]) |
| { |
| TCU_FAIL("Invalid type value returned by GetDebugMessageLog"); |
| } |
| |
| if ((GLuint)(i + half_count) != ids[i]) |
| { |
| TCU_FAIL("Invalid id value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_SEVERITY_MEDIUM != severities[i]) |
| { |
| TCU_FAIL("Invalid severity value returned by GetDebugMessageLog"); |
| } |
| |
| // DebugMessageInsert's length does not include null-terminated character (if length is positive) |
| // But GetDebugMessageLog's length include null-terminated character |
| // OpenGL 4.5 Core Spec, Page 530 and Page 535 |
| if (label_length + 1 != lengths[i]) |
| { |
| TCU_FAIL("Invalid length value returned by GetDebugMessageLog"); |
| } |
| |
| if (0 != strcmp(label, &messageLog[i * (label_length + 1)])) |
| { |
| TCU_FAIL("Invalid message returned by GetDebugMessageLog"); |
| } |
| } |
| |
| /* */ |
| memset(&messageLog[0], 0, messageLog.size()); |
| |
| ret = m_gl->getDebugMessageLog(rest_count /* count */, buf_size /* bufSize */, &sources[0] /* sources */, |
| &types[0] /* types */, &ids[0] /* ids */, &severities[0] /* severities */, |
| &lengths[0] /* lengths */, &messageLog[0] /* messageLog */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog"); |
| |
| if (ret != 1) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "GetDebugMessageLog returned unexpected number of messages: " << ret |
| << ", expected 1" << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid number of meessages"); |
| } |
| |
| m_gl->getIntegerv(GL_DEBUG_LOGGED_MESSAGES, &n_debug_messages); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| if (n_debug_messages != 0) |
| { |
| m_testCtx.getLog() |
| << tcu::TestLog::Message << "State of DEBUG_LOGGED_MESSAGES: " << n_debug_messages << ", expected 1" |
| << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid state of DEBUG_LOGGED_MESSAGES"); |
| } |
| |
| if (GL_DEBUG_SOURCE_APPLICATION != sources[0]) |
| { |
| TCU_FAIL("Invalid source value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_TYPE_ERROR != types[0]) |
| { |
| TCU_FAIL("Invalid type value returned by GetDebugMessageLog"); |
| } |
| |
| if ((GLuint)(max_debug_messages - 1) != ids[0]) |
| { |
| TCU_FAIL("Invalid id value returned by GetDebugMessageLog"); |
| } |
| |
| if (GL_DEBUG_SEVERITY_MEDIUM != severities[0]) |
| { |
| TCU_FAIL("Invalid severity value returned by GetDebugMessageLog"); |
| } |
| |
| // DebugMessageInsert's length does not include null-terminated character (if length is positive) |
| // But GetDebugMessageLog's length include null-terminated character |
| // OpenGL 4.5 Core Spec, Page 530 and Page 535 |
| if (label_length + 1 != lengths[0]) |
| { |
| TCU_FAIL("Invalid length value returned by GetDebugMessageLog"); |
| } |
| |
| if (0 != strcmp(label, &messageLog[0])) |
| { |
| TCU_FAIL("Invalid message returned by GetDebugMessageLog"); |
| } |
| } |
| |
| /* Set result */ |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| |
| /* Done */ |
| TestBase::done(); |
| |
| return tcu::TestNode::STOP; |
| } |
| |
| /** Debug callback used by the test, increase counter by one |
| * |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param info Pointer to uint counter |
| **/ |
| void ReceivingMessagesTest::debug_proc(glw::GLenum /* source */, glw::GLenum /* type */, glw::GLuint /* id */, |
| glw::GLenum /* severity */, glw::GLsizei /* length */, |
| const glw::GLchar* /* message */, const void* info) |
| { |
| GLuint* counter = (GLuint*)info; |
| |
| *counter += 1; |
| } |
| |
| /** Inspects state of DEBUG_OUTPUT and debug callback |
| * |
| * @param expected_state Expected state of DEBUG_OUTPUT |
| * @param expected_callback Expected state of DEBUG_CALLBACK_FUNCTION |
| * @param expected_user_info Expected state of DEBUG_CALLBACK_USER_PARAM |
| **/ |
| void ReceivingMessagesTest::inspectDebugState(GLboolean expected_state, GLDEBUGPROC expected_callback, |
| GLvoid* expected_user_info) const |
| { |
| GLboolean debug_state = -1; |
| m_gl->getBooleanv(GL_DEBUG_OUTPUT, &debug_state); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetBooleanv"); |
| |
| if (expected_state != debug_state) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "State of DEBUG_OUTPUT: " << debug_state |
| << ", expected " << expected_state << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid state of DEBUG_OUTPUT"); |
| } |
| |
| GLvoid* callback_procedure = 0; |
| m_gl->getPointerv(GL_DEBUG_CALLBACK_FUNCTION, &callback_procedure); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetPointerv"); |
| |
| if (expected_callback != callback_procedure) |
| { |
| TCU_FAIL("Invalid state of DEBUG_CALLBACK_FUNCTION"); |
| } |
| |
| GLvoid* callback_user_info = 0; |
| m_gl->getPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &callback_user_info); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetPointerv"); |
| |
| if (expected_user_info != callback_user_info) |
| { |
| TCU_FAIL("Invalid state of DEBUG_CALLBACK_USER_PARAM"); |
| } |
| } |
| |
| /** Inspects value of counter used by callback |
| * |
| * @param callback_counter Reference to counter |
| * @param expected_number_of_messages Expected value of counter |
| **/ |
| void ReceivingMessagesTest::inspectCallbackCounter(GLuint& callback_counter, GLuint expected_number_of_messages) const |
| { |
| m_gl->finish(); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish"); |
| |
| if (expected_number_of_messages != callback_counter) |
| { |
| m_testCtx.getLog() |
| << tcu::TestLog::Message << "Debug callback was executed invalid number of times: " << callback_counter |
| << ", expected " << expected_number_of_messages << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid execution of debug callback"); |
| } |
| } |
| |
| /** Inspects amount of messages stored in log |
| * |
| * @param expected_number_of_messages Expected number of messages |
| **/ |
| void ReceivingMessagesTest::inspectMessageLog(GLuint expected_number_of_messages) const |
| { |
| static const size_t bufSize = 32; |
| static const size_t read_messages = 4; |
| |
| GLchar messageLog[bufSize]; |
| GLenum sources[read_messages]; |
| GLenum types[read_messages]; |
| GLuint ids[read_messages]; |
| GLenum severities[read_messages]; |
| GLsizei lengths[read_messages]; |
| |
| GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, sources /* sources */, |
| types /* types */, ids /* ids */, severities /* severities */, |
| lengths /* lengths */, messageLog /* messageLog */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog"); |
| |
| if (expected_number_of_messages != ret) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "GetDebugMessageLog returned invalid number of messages: " << ret |
| << ", expected " << expected_number_of_messages << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid value returned by GetDebugMessageLog"); |
| } |
| } |
| |
| /** Constructor |
| * |
| * @param testCtx Test context |
| * @param is_debug Selects if debug or non-debug context should be used |
| * @param name Name of test |
| **/ |
| GroupsTest::GroupsTest(tcu::TestContext& testCtx, glu::ApiType apiType) |
| : TestCase(testCtx, "groups", "Verifies that groups can be used to control generated messages") |
| , TestBase(testCtx, apiType, true /* is_debug */) |
| { |
| /* Nothing to be done */ |
| } |
| |
| /** Execute test |
| * |
| * @return tcu::TestNode::STOP |
| **/ |
| tcu::TestNode::IterateResult GroupsTest::iterate() |
| { |
| static const GLchar label[] = "foo"; |
| static const size_t label_length = sizeof(label) / sizeof(label[0]) - 1; |
| |
| /* Initialize render context */ |
| TestBase::init(); |
| |
| cleanMessageLog(m_gl); |
| |
| /* |
| * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 1; |
| */ |
| inspectGroupStack(1); |
| |
| /* |
| * - insert message with <type> DEBUG_TYPE_ERROR; |
| * - inspect message log to check if the message is reported; |
| * - insert message with <type> DEBUG_TYPE_OTHER; |
| * - inspect message log to check if the message is reported; |
| */ |
| { |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| } |
| |
| /* |
| * - push debug group with unique <id> and <message>; |
| * - inspect message log to check if the message about push is reported; |
| * - disable messages with <type> DEBUG_TYPE_ERROR; |
| * - insert message with <type> DEBUG_TYPE_ERROR; |
| * - inspect message log to check there are no messages; |
| * - insert message with <type> DEBUG_TYPE_OTHER; |
| * - inspect message log to check if the message is reported; |
| */ |
| { |
| m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 0xabcd0123 /* id */, -1 /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_PUSH_GROUP /* type */, |
| 0xabcd0123 /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */, |
| label); |
| |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_ERROR /* type */, |
| GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| verifyEmptyLog(); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| } |
| |
| /* |
| * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 2; |
| */ |
| inspectGroupStack(2); |
| |
| /* |
| * - push debug group with unique <id> and <message>; |
| * - inspect message log to check if the message about push is reported; |
| * - disable messages with <type> DEBUG_TYPE_OTHER; |
| * - insert message with <type> DEBUG_TYPE_ERROR; |
| * - inspect message log to check there are no messages; |
| * - insert message with <type> DEBUG_TYPE_OTHER; |
| * - inspect message log to check there are no messages; |
| */ |
| { |
| m_gl->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION /* source */, 0x0123abcd /* id */, -1 /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "PushDebugGroup"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_PUSH_GROUP /* type */, |
| 0x0123abcd /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */, |
| label); |
| |
| m_gl->debugMessageControl(GL_DONT_CARE /* source */, GL_DEBUG_TYPE_OTHER /* type */, |
| GL_DONT_CARE /* severity */, 0 /* counts */, 0 /* ids */, GL_FALSE /* enabled */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageControl"); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| verifyEmptyLog(); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| verifyEmptyLog(); |
| } |
| |
| /* |
| * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 3; |
| */ |
| inspectGroupStack(3); |
| |
| /* |
| * - pop debug group; |
| * - inspect message log to check if the message about pop is reported and |
| * corresponds with the second push; |
| * - insert message with <type> DEBUG_TYPE_ERROR; |
| * - inspect message log to check there are no messages; |
| * - insert message with <type> DEBUG_TYPE_OTHER; |
| * - inspect message log to check if the message is reported; |
| */ |
| { |
| m_gl->popDebugGroup(); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_POP_GROUP /* type */, |
| 0x0123abcd /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */, |
| label); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| verifyEmptyLog(); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| } |
| |
| /* |
| * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 2; |
| */ |
| inspectGroupStack(2); |
| |
| /* |
| * - pop debug group; |
| * - inspect message log to check if the message about pop is reported and |
| * corresponds with the first push; |
| * - insert message with <type> DEBUG_TYPE_ERROR; |
| * - inspect message log to check if the message is reported; |
| * - insert message with <type> DEBUG_TYPE_OTHER; |
| * - inspect message log to check if the message is reported; |
| */ |
| { |
| m_gl->popDebugGroup(); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "PopDebugGroup"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_POP_GROUP /* type */, |
| 0xabcd0123 /* id */, GL_DEBUG_SEVERITY_NOTIFICATION /* severity */, label_length /* length */, |
| label); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| inspectMessageLog(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_OTHER /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, label_length /* length */, label); |
| } |
| |
| /* |
| * - check state of DEBUG_GROUP_STACK_DEPTH; It should be 1; |
| */ |
| inspectGroupStack(1); |
| |
| /* Set result */ |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| |
| /* Done */ |
| TestBase::done(); |
| |
| return tcu::TestNode::STOP; |
| } |
| |
| /** Inspects amount of groups on stack |
| * |
| * @param expected_depth Expected number of groups |
| **/ |
| void GroupsTest::inspectGroupStack(GLuint expected_depth) const |
| { |
| GLint stack_depth = 0; |
| |
| m_gl->getIntegerv(GL_DEBUG_GROUP_STACK_DEPTH, &stack_depth); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetIntegerv"); |
| |
| if (expected_depth != (GLuint)stack_depth) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "State of DEBUG_GROUP_STACK_DEPTH: " << stack_depth << ", expected " |
| << expected_depth << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid state of DEBUG_GROUP_STACK_DEPTH"); |
| } |
| } |
| |
| /** Inspects first message stored in log |
| * |
| * @param expected_source Expected source of messages |
| * @param expected_type Expected type of messages |
| * @param expected_id Expected id of messages |
| * @param expected_severity Expected severity of messages |
| * @param expected_length Expected length of messages |
| * @param expected_label Expected label of messages |
| **/ |
| void GroupsTest::inspectMessageLog(glw::GLenum expected_source, glw::GLenum expected_type, glw::GLuint expected_id, |
| glw::GLenum expected_severity, glw::GLsizei expected_length, |
| const glw::GLchar* expected_label) const |
| { |
| static const size_t bufSize = 32; |
| static const size_t read_messages = 1; |
| |
| GLchar messageLog[bufSize]; |
| GLenum source; |
| GLenum type; |
| GLuint id; |
| GLenum severity; |
| GLsizei length; |
| |
| GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, &source /* sources */, |
| &type /* types */, &id /* ids */, &severity /* severities */, |
| &length /* lengths */, messageLog /* messageLog */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog"); |
| |
| if (0 == ret) |
| { |
| TCU_FAIL("GetDebugMessageLog returned 0 messages"); |
| } |
| |
| if (expected_source != source) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid source: " << source |
| << ", expected " << expected_source << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid source of message"); |
| } |
| |
| if (expected_type != type) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid type: " << type |
| << ", expected " << expected_type << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid type of message"); |
| } |
| |
| if (expected_id != id) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid id: " << id |
| << ", expected " << expected_id << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid id of message"); |
| } |
| |
| if (expected_severity != severity) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Got message with invalid severity: " << severity << ", expected " |
| << expected_severity << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid severity of message"); |
| } |
| |
| // DebugMessageInsert's length does not include null-terminated character (if length is positive) |
| // But GetDebugMessageLog's length include null-terminated character |
| // OpenGL 4.5 Core Spec, Page 530 and Page 535 |
| if (expected_length + 1 != length) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message << "Got message with invalid length: " << length |
| << ", expected " << expected_length << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid length of message"); |
| } |
| |
| if (0 != strcmp(expected_label, messageLog)) |
| { |
| m_testCtx.getLog() << tcu::TestLog::Message |
| << "Got message with invalid message: " << messageLog << ", expected " |
| << expected_label << tcu::TestLog::EndMessage; |
| |
| TCU_FAIL("Invalid message"); |
| } |
| } |
| |
| /** Verifies that message log is empty |
| * |
| **/ |
| void GroupsTest::verifyEmptyLog() const |
| { |
| static const size_t bufSize = 32; |
| static const size_t read_messages = 1; |
| |
| GLchar messageLog[bufSize]; |
| GLenum source; |
| GLenum type; |
| GLuint id; |
| GLenum severity; |
| GLsizei length; |
| |
| GLuint ret = m_gl->getDebugMessageLog(read_messages /* count */, bufSize /* bufSize */, &source /* sources */, |
| &type /* types */, &id /* ids */, &severity /* severities */, |
| &length /* lengths */, messageLog /* messageLog */); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GetDebugMessageLog"); |
| |
| if (0 != ret) |
| { |
| TCU_FAIL("GetDebugMessageLog returned unexpected messages"); |
| } |
| } |
| |
| /** Constructor |
| * |
| * @param testCtx Test context |
| * @param is_debug Selects if debug or non-debug context should be used |
| * @param name Name of test |
| **/ |
| SynchronousCallsTest::SynchronousCallsTest(tcu::TestContext& testCtx, glu::ApiType apiType) |
| : TestCase(testCtx, "synchronous_calls", "Verifies that messages can be received") |
| , TestBase(testCtx, apiType, true /* is_debug */) |
| { |
| /* Create pthread_key_t visible to all threads |
| * The key has value NULL associated with it in all existing |
| * or about to be created threads |
| */ |
| m_uid = 0; |
| } |
| |
| /** Execute test |
| * |
| * @return tcu::TestNode::STOP |
| **/ |
| tcu::TestNode::IterateResult SynchronousCallsTest::iterate() |
| { |
| m_uid++; |
| |
| /* associate some unique id with the current thread */ |
| m_tls.set((void*)(deUintptr)m_uid); |
| |
| static const GLchar label[] = "foo"; |
| |
| GLuint buffer_id = 0; |
| |
| /* Initialize render context */ |
| TestBase::init(); |
| |
| /* - set callback_executed to 0; */ |
| int callback_executed = 0; |
| |
| /* |
| *- enable DEBUG_OUTPUT_SYNCHRONOUS; |
| */ |
| m_gl->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Enable"); |
| |
| /* |
| * - register debug message callback with DebugMessageCallback; Provide the |
| * instance of UserParam structure as <userParam>; Routine should do the |
| * following: |
| * * set callback_executed to 1; |
| */ |
| m_gl->debugMessageCallback(debug_proc, &callback_executed); |
| try |
| { |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageCallback"); |
| |
| /* |
| * - insert a message with DebugMessageInsert; |
| */ |
| m_gl->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION /* source */, GL_DEBUG_TYPE_ERROR /* type */, 11 /* id */, |
| GL_DEBUG_SEVERITY_HIGH /* severity */, -1 /* length */, label); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "DebugMessageInsert"); |
| |
| /* Make sure execution finished before we check results */ |
| m_gl->finish(); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish"); |
| |
| /* |
| * - check if: |
| * * callback_executed is set to 1; |
| */ |
| if (1 != callback_executed) |
| { |
| TCU_FAIL("callback_executed is not set to 1"); |
| } |
| |
| /* Check that the message was recorded by the current thread */ |
| if ((deUintptr)(m_tls.get()) != m_uid) |
| { |
| TCU_FAIL("thread id stored by callback is not the same as \"test\" thread"); |
| } |
| |
| /* |
| * - reset callback_executed; |
| */ |
| callback_executed = 0; |
| |
| /* |
| * - execute BindBufferBase with GL_ARRAY_BUFFER <target>, GL_INVALID_ENUM |
| * error should be generated; |
| */ |
| m_gl->genBuffers(1, &buffer_id); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "GenBuffers"); |
| |
| m_gl->bindBufferBase(GL_ARRAY_BUFFER, 0 /* index */, buffer_id); |
| if (GL_INVALID_ENUM != m_gl->getError()) |
| { |
| TCU_FAIL("Unexpected error generated"); |
| } |
| |
| /* Make sure execution finished before we check results */ |
| m_gl->finish(); |
| GLU_EXPECT_NO_ERROR(m_gl->getError(), "Finish"); |
| |
| /* |
| * - test pass if: |
| * * callback_executed is set to 0 - implementation does not send messages; |
| * * callback_executed is set to 1 and thread_id is the same |
| * as "test" thread - implementation sent message to proper thread; |
| */ |
| if (1 == callback_executed) |
| { |
| /* Check that the error was recorded by the current thread */ |
| if ((deUintptr)(m_tls.get()) != m_uid) |
| { |
| TCU_FAIL("thread id stored by callback is not the same as \"test\" thread"); |
| } |
| } |
| |
| /* Clean */ |
| m_gl->deleteBuffers(1, &buffer_id); |
| buffer_id = 0; |
| } |
| catch (const std::exception& exc) |
| { |
| if (0 != buffer_id) |
| { |
| m_gl->deleteBuffers(1, &buffer_id); |
| buffer_id = 0; |
| } |
| |
| TCU_FAIL(exc.what()); |
| } |
| |
| /* Set result */ |
| m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); |
| |
| /* Done */ |
| TestBase::done(); |
| |
| return tcu::TestNode::STOP; |
| } |
| |
| /** Destructor */ |
| SynchronousCallsTest::~SynchronousCallsTest(void) |
| { |
| } |
| |
| /** Debug callback used by the test, sets callback_executed to 1 and stores 0 to tls |
| * |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param ignored |
| * @param info Pointer to uint counter |
| **/ |
| void SynchronousCallsTest::debug_proc(glw::GLenum /* source */, glw::GLenum /* type */, glw::GLuint /* id */, |
| glw::GLenum /* severity */, glw::GLsizei /* length */, |
| const glw::GLchar* /* message */, const void* info) |
| { |
| int* callback_executed = (int*)info; |
| |
| *callback_executed = 1; |
| } |
| } /* KHRDebug */ |
| |
| /** Constructor. |
| * |
| * @param context Rendering context. |
| **/ |
| KHRDebugTests::KHRDebugTests(tcu::TestContext& testCtx, glu::ApiType apiType) |
| : TestCaseGroup(testCtx, "khr_debug", "Verifies \"khr debug\" functionality") |
| , m_apiType(apiType) |
| |
| { |
| /* Left blank on purpose */ |
| } |
| |
| /** Initializes a khr_debug test group. |
| * |
| **/ |
| void KHRDebugTests::init(void) |
| { |
| addChild(new KHRDebug::APIErrorsTest(m_testCtx, m_apiType, false, "api_errors_non_debug")); |
| addChild(new KHRDebug::LabelsTest(m_testCtx, m_apiType, false, "labels_non_debug")); |
| addChild(new KHRDebug::ReceivingMessagesTest(m_testCtx, m_apiType)); |
| addChild(new KHRDebug::GroupsTest(m_testCtx, m_apiType)); |
| addChild(new KHRDebug::APIErrorsTest(m_testCtx, m_apiType, true, "api_errors_debug")); |
| addChild(new KHRDebug::LabelsTest(m_testCtx, m_apiType, true, "labels_debug")); |
| addChild(new KHRDebug::SynchronousCallsTest(m_testCtx, m_apiType)); |
| } |
| |
| } /* glcts namespace */ |