1/*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2017 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file glcRobustnessTests.cpp 21 * \brief Conformance tests for the Robustness feature functionality. 22 */ /*-------------------------------------------------------------------*/ 23 24#include "glcRobustnessTests.hpp" 25#include "deSharedPtr.hpp" 26#include "glcRobustBufferAccessBehaviorTests.hpp" 27#include "gluContextInfo.hpp" 28#include "gluPlatform.hpp" 29#include "gluRenderContext.hpp" 30#include "glwEnums.hpp" 31#include "glwFunctions.hpp" 32#include "tcuCommandLine.hpp" 33#include "tcuTestLog.hpp" 34#include <cstring> 35 36using namespace glw; 37using namespace glcts::RobustBufferAccessBehavior; 38 39namespace glcts 40{ 41 42namespace ResetNotificationStrategy 43{ 44 45class RobustnessBase : public tcu::TestCase 46{ 47public: 48 RobustnessBase(tcu::TestContext& testCtx, const char* name, const char* description, glu::ApiType apiType); 49 50 glu::RenderContext* createRobustContext(glu::ResetNotificationStrategy reset); 51 52private: 53 glu::ApiType m_ApiType; 54}; 55 56RobustnessBase::RobustnessBase(tcu::TestContext& testCtx, const char* name, const char* description, 57 glu::ApiType apiType) 58 : tcu::TestCase(testCtx, name, description), m_ApiType(apiType) 59{ 60} 61 62glu::RenderContext* RobustnessBase::createRobustContext(glu::ResetNotificationStrategy reset) 63{ 64 /* Create test context to verify if GL_KHR_robustness extension is available */ 65 { 66 deqp::Context context(m_testCtx, glu::ContextType(m_ApiType)); 67 if (!context.getContextInfo().isExtensionSupported("GL_KHR_robustness") && 68 !contextSupports(context.getRenderContext().getType(), glu::ApiType::es(3, 2))) 69 { 70 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, 71 "GL_KHR_robustness extension not supported"); 72 return NULL; 73 } 74 } 75 76 glu::RenderConfig renderCfg(glu::ContextType(m_ApiType, glu::CONTEXT_ROBUST)); 77 const tcu::CommandLine& commandLine = m_testCtx.getCommandLine(); 78 glu::parseRenderConfig(&renderCfg, commandLine); 79 80 if (commandLine.getSurfaceType() == tcu::SURFACETYPE_WINDOW) 81 renderCfg.resetNotificationStrategy = reset; 82 else 83 throw tcu::NotSupportedError("Test not supported in non-windowed context"); 84 85 /* Try to create core/es robusness context */ 86 return createRenderContext(m_testCtx.getPlatform(), commandLine, renderCfg); 87} 88 89class NoResetNotificationCase : public RobustnessBase 90{ 91 typedef glw::GLenum(GLW_APIENTRY* PFNGLGETGRAPHICSRESETSTATUS)(); 92 93public: 94 NoResetNotificationCase(tcu::TestContext& testCtx, const char* name, const char* description, glu::ApiType apiType) 95 : RobustnessBase(testCtx, name, description, apiType) 96 { 97 } 98 99 virtual IterateResult iterate(void) 100 { 101 glu::ResetNotificationStrategy strategy = glu::RESET_NOTIFICATION_STRATEGY_NO_RESET_NOTIFICATION; 102 de::SharedPtr<glu::RenderContext> robustContext(createRobustContext(strategy)); 103 if (!robustContext.get()) 104 return STOP; 105 106 glw::GLint reset = 0; 107 108 const glw::Functions& gl = robustContext->getFunctions(); 109 gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset); 110 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv"); 111 112 if (reset != GL_NO_RESET_NOTIFICATION) 113 { 114 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! glGet returned wrong value [" << reset 115 << ", expected " << GL_NO_RESET_NOTIFICATION << "]." << tcu::TestLog::EndMessage; 116 117 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 118 return STOP; 119 } 120 121 glw::GLint status = gl.getGraphicsResetStatus(); 122 if (status != GL_NO_ERROR) 123 { 124 m_testCtx.getLog() << tcu::TestLog::Message 125 << "Test failed! glGetGraphicsResetStatus returned wrong value [" << status 126 << ", expected " << GL_NO_ERROR << "]." << tcu::TestLog::EndMessage; 127 128 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 129 return STOP; 130 } 131 132 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 133 return STOP; 134 } 135}; 136 137class LoseContextOnResetCase : public RobustnessBase 138{ 139public: 140 LoseContextOnResetCase(tcu::TestContext& testCtx, const char* name, const char* description, glu::ApiType apiType) 141 : RobustnessBase(testCtx, name, description, apiType) 142 { 143 } 144 145 virtual IterateResult iterate(void) 146 { 147 glu::ResetNotificationStrategy strategy = glu::RESET_NOTIFICATION_STRATEGY_LOSE_CONTEXT_ON_RESET; 148 de::SharedPtr<glu::RenderContext> robustContext(createRobustContext(strategy)); 149 if (!robustContext.get()) 150 return STOP; 151 152 glw::GLint reset = 0; 153 154 const glw::Functions& gl = robustContext->getFunctions(); 155 gl.getIntegerv(GL_RESET_NOTIFICATION_STRATEGY, &reset); 156 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv"); 157 158 if (reset != GL_LOSE_CONTEXT_ON_RESET) 159 { 160 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! glGet returned wrong value [" << reset 161 << ", expected " << GL_LOSE_CONTEXT_ON_RESET << "]." << tcu::TestLog::EndMessage; 162 163 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 164 return STOP; 165 } 166 167 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 168 return STOP; 169 } 170}; 171 172} // ResetNotificationStrategy namespace 173 174namespace RobustBufferAccessBehavior 175{ 176 177static deqp::Context* createContext(tcu::TestContext& testCtx, glu::ApiType apiType) 178{ 179 deqp::Context* context = new deqp::Context(testCtx, glu::ContextType(apiType)); 180 if (!context) 181 { 182 testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Pointer to context is NULL."); 183 return DE_NULL; 184 } 185 186 if (!(contextSupports(context->getRenderContext().getType(), glu::ApiType::es(3, 2)) || 187 (context->getContextInfo().isExtensionSupported("GL_KHR_robustness") && 188 context->getContextInfo().isExtensionSupported("GL_KHR_robust_buffer_access_behavior")))) 189 { 190 testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); 191 delete context; 192 return DE_NULL; 193 } 194 195 return context; 196} 197 198/** Implementation of test GetnUniformTest. Description follows: 199 * 200 * This test verifies if read uniform variables to the buffer with bufSize less than expected result with GL_INVALID_OPERATION error; 201 **/ 202class GetnUniformTest : public tcu::TestCase 203{ 204public: 205 /* Public methods */ 206 GetnUniformTest(tcu::TestContext& testCtx, glu::ApiType apiType); 207 virtual ~GetnUniformTest() 208 { 209 } 210 211 /* Public methods inherited from TestCase */ 212 virtual tcu::TestNode::IterateResult iterate(void); 213 214private: 215 /* Private methods */ 216 std::string getComputeShader(bool glslES320); 217 218 bool verifyResult(const void* inputData, const void* resultData, int size, const char* method); 219 bool verifyError(glw::GLint error, glw::GLint expectedError, const char* method); 220 221 glu::ApiType m_ApiType; 222}; 223 224/** Constructor 225 * 226 * @param context Test context 227 **/ 228GetnUniformTest::GetnUniformTest(tcu::TestContext& testCtx, glu::ApiType apiType) 229 : tcu::TestCase(testCtx, "getnuniform", "Verifies if read uniform variables to the buffer with bufSize less than " 230 "expected result with GL_INVALID_OPERATION") 231 , m_ApiType(apiType) 232{ 233 /* Nothing to be done here */ 234} 235 236/** Execute test 237 * 238 * @return tcu::TestNode::STOP 239 **/ 240tcu::TestNode::IterateResult GetnUniformTest::iterate() 241{ 242 de::SharedPtr<deqp::Context> context(createContext(m_testCtx, m_ApiType)); 243 if (!context.get()) 244 return STOP; 245 246 glu::RenderContext& renderContext = context->getRenderContext(); 247 const Functions& gl = renderContext.getFunctions(); 248 249 const GLfloat input4f[] = { 1.0f, 5.4f, 3.14159f, 1.28f }; 250 const GLint input3i[] = { 10, -20, -30 }; 251 const GLuint input4ui[] = { 10, 20, 30, 40 }; 252 253 /* Test result indicator */ 254 bool test_result = true; 255 256 /* Iterate over all cases */ 257 Program program(gl); 258 259 /* Compute Shader */ 260 bool glslES320 = contextSupports(renderContext.getType(), glu::ApiType::es(3, 2)); 261 const std::string& cs = getComputeShader(glslES320); 262 263 /* Shaders initialization */ 264 program.Init(cs /* cs */, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */); 265 program.Use(); 266 267 /* Initialize shader storage buffer */ 268 GLuint buf; 269 270 gl.genBuffers(1, &buf); 271 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers"); 272 273 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buf); 274 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase"); 275 276 gl.bufferData(GL_SHADER_STORAGE_BUFFER, 16, DE_NULL, GL_STREAM_DRAW); 277 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData"); 278 279 /* passing uniform values */ 280 gl.programUniform4fv(program.m_id, 11, 1, input4f); 281 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform4fv"); 282 283 gl.programUniform3iv(program.m_id, 12, 1, input3i); 284 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform3iv"); 285 286 gl.programUniform4uiv(program.m_id, 13, 1, input4ui); 287 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramUniform4uiv"); 288 289 gl.dispatchCompute(1, 1, 1); 290 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute"); 291 292 /* veryfing gfetnUniform error messages */ 293 GLfloat result4f[4]; 294 GLint result3i[3]; 295 GLuint result4ui[4]; 296 297 gl.getnUniformfv(program.m_id, 11, sizeof(GLfloat) * 4, result4f); 298 test_result = test_result && 299 verifyResult((void*)input4f, (void*)result4f, sizeof(GLfloat) * 4, "getnUniformfv [false negative]"); 300 test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformfv [false negative]"); 301 302 gl.getnUniformfv(program.m_id, 11, sizeof(GLfloat) * 3, result4f); 303 test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformfv [false positive]"); 304 305 gl.getnUniformiv(program.m_id, 12, sizeof(GLint) * 3, result3i); 306 test_result = test_result && 307 verifyResult((void*)input3i, (void*)result3i, sizeof(GLint) * 3, "getnUniformiv [false negative]"); 308 test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformiv [false negative]"); 309 310 gl.getnUniformiv(program.m_id, 12, sizeof(GLint) * 2, result3i); 311 test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformiv [false positive]"); 312 313 gl.getnUniformuiv(program.m_id, 13, sizeof(GLuint) * 4, result4ui); 314 test_result = test_result && verifyResult((void*)input4ui, (void*)result4ui, sizeof(GLuint) * 4, 315 "getnUniformuiv [false negative]"); 316 test_result = test_result && verifyError(gl.getError(), GL_NO_ERROR, "getnUniformuiv [false negative]"); 317 318 gl.getnUniformuiv(program.m_id, 13, sizeof(GLuint) * 3, result4ui); 319 test_result = test_result && verifyError(gl.getError(), GL_INVALID_OPERATION, "getnUniformuiv [false positive]"); 320 321 /* Set result */ 322 if (true == test_result) 323 { 324 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 325 } 326 else 327 { 328 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 329 } 330 331 gl.deleteBuffers(1, &buf); 332 333 /* Done */ 334 return tcu::TestNode::STOP; 335} 336 337std::string GetnUniformTest::getComputeShader(bool glslES320) 338{ 339 std::stringstream shader; 340 shader << "#version " << (glslES320 ? "320 es\n" : "450\n"); 341 shader << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n" 342 "layout (location = 11) uniform vec4 inputf;\n" 343 "layout (location = 12) uniform ivec3 inputi;\n" 344 "layout (location = 13) uniform uvec4 inputu;\n" 345 "layout (std140, binding = 0) buffer ssbo {\n" 346 " float valuef;\n" 347 " int valuei;\n" 348 " uint valueu;\n" 349 "};\n" 350 "void main()\n" 351 "{\n" 352 " valuef = inputf.r + inputf.g + inputf.b + inputf.a;\n" 353 " valuei = inputi.r + inputi.g + inputi.b;\n" 354 " valueu = inputu.r + inputu.g + inputu.b + inputu.a;\n" 355 "}\n"; 356 return shader.str(); 357} 358 359bool GetnUniformTest::verifyResult(const void* inputData, const void* resultData, int size, const char* method) 360{ 361 int diff = memcmp(inputData, resultData, size); 362 if (diff != 0) 363 { 364 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " result is not as expected." 365 << tcu::TestLog::EndMessage; 366 367 return false; 368 } 369 370 return true; 371} 372 373bool GetnUniformTest::verifyError(GLint error, GLint expectedError, const char* method) 374{ 375 if (error != expectedError) 376 { 377 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " throws unexpected error [" 378 << error << "]." << tcu::TestLog::EndMessage; 379 380 return false; 381 } 382 383 return true; 384} 385 386/** Implementation of test ReadnPixelsTest. Description follows: 387 * 388 * This test verifies if read pixels to the buffer with bufSize less than expected result with GL_INVALID_OPERATION error; 389 **/ 390class ReadnPixelsTest : public tcu::TestCase 391{ 392public: 393 /* Public methods */ 394 ReadnPixelsTest(tcu::TestContext& testCtx, glu::ApiType apiType); 395 virtual ~ReadnPixelsTest() 396 { 397 } 398 399 /* Public methods inherited from TestCase */ 400 virtual tcu::TestNode::IterateResult iterate(void); 401 402private: 403 /* Private methods */ 404 void cleanTexture(deqp::Context& context, glw::GLuint texture_id); 405 bool verifyResults(deqp::Context& context); 406 bool verifyError(glw::GLint error, glw::GLint expectedError, const char* method); 407 408 glu::ApiType m_ApiType; 409}; 410 411/** Constructor 412 * 413 * @param context Test context 414 **/ 415ReadnPixelsTest::ReadnPixelsTest(tcu::TestContext& testCtx, glu::ApiType apiType) 416 : tcu::TestCase(testCtx, "readnpixels", 417 "Verifies if read pixels to the buffer with bufSize less than expected result " 418 "with GL_INVALID_OPERATION error") 419 , m_ApiType(apiType) 420{ 421 /* Nothing to be done here */ 422} 423 424/** Execute test 425 * 426 * @return tcu::TestNode::STOP 427 **/ 428tcu::TestNode::IterateResult ReadnPixelsTest::iterate() 429{ 430 de::SharedPtr<deqp::Context> context(createContext(m_testCtx, m_ApiType)); 431 if (!context.get()) 432 return STOP; 433 434 static const GLuint elements[] = { 435 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 6, 0, 6, 7, 0, 7, 8, 0, 8, 1, 436 }; 437 438 static const GLfloat vertices[] = { 439 0.0f, 0.0f, 0.0f, 1.0f, /* 0 */ 440 -1.0f, 0.0f, 0.0f, 1.0f, /* 1 */ 441 -1.0f, 1.0f, 0.0f, 1.0f, /* 2 */ 442 0.0f, 1.0f, 0.0f, 1.0f, /* 3 */ 443 1.0f, 1.0f, 0.0f, 1.0f, /* 4 */ 444 1.0f, 0.0f, 0.0f, 1.0f, /* 5 */ 445 1.0f, -1.0f, 0.0f, 1.0f, /* 6 */ 446 0.0f, -1.0f, 0.0f, 1.0f, /* 7 */ 447 -1.0f, -1.0f, 0.0f, 1.0f, /* 8 */ 448 }; 449 450 bool glslES320 = contextSupports(context->getRenderContext().getType(), glu::ApiType::es(3, 2)); 451 std::string fs("#version "); 452 fs += (glslES320 ? "320 es\n" : "450\n"); 453 fs += "layout (location = 0) out lowp uvec4 out_fs_color;\n" 454 "\n" 455 "void main()\n" 456 "{\n" 457 " out_fs_color = uvec4(1, 0, 0, 1);\n" 458 "}\n" 459 "\n"; 460 461 std::string vs("#version "); 462 vs += (glslES320 ? "320 es\n" : "450\n"); 463 vs += "layout (location = 0) in vec4 in_vs_position;\n" 464 "\n" 465 "void main()\n" 466 "{\n" 467 " gl_Position = in_vs_position;\n" 468 "}\n" 469 "\n"; 470 471 static const GLuint height = 8; 472 static const GLuint width = 8; 473 static const GLuint n_vertices = 24; 474 475 /* GL entry points */ 476 const Functions& gl = context->getRenderContext().getFunctions(); 477 478 /* Test case objects */ 479 Program program(gl); 480 Texture texture(gl); 481 Buffer elements_buffer(gl); 482 Buffer vertices_buffer(gl); 483 VertexArray vao(gl); 484 485 /* Vertex array initialization */ 486 VertexArray::Generate(gl, vao.m_id); 487 VertexArray::Bind(gl, vao.m_id); 488 489 /* Texture initialization */ 490 Texture::Generate(gl, texture.m_id); 491 Texture::Bind(gl, texture.m_id, GL_TEXTURE_2D); 492 Texture::Storage(gl, GL_TEXTURE_2D, 1, GL_R8UI, width, height, 0); 493 Texture::Bind(gl, 0, GL_TEXTURE_2D); 494 495 /* Framebuffer initialization */ 496 GLuint fbo; 497 gl.genFramebuffers(1, &fbo); 498 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers"); 499 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); 500 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer"); 501 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.m_id, 0); 502 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D"); 503 504 /* Buffers initialization */ 505 elements_buffer.InitData(GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(elements), elements); 506 vertices_buffer.InitData(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, sizeof(vertices), vertices); 507 508 /* Shaders initialization */ 509 program.Init("" /* cs */, fs, "" /* gs */, "" /* tcs */, "" /* tes */, vs); 510 Program::Use(gl, program.m_id); 511 512 /* Vertex buffer initialization */ 513 vertices_buffer.Bind(); 514 gl.bindVertexBuffer(0 /* bindindex = location */, vertices_buffer.m_id, 0 /* offset */, 16 /* stride */); 515 gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 16, NULL); 516 gl.enableVertexAttribArray(0 /* location */); 517 518 /* Binding elements/indices buffer */ 519 elements_buffer.Bind(); 520 521 cleanTexture(*context, texture.m_id); 522 523 gl.drawElements(GL_TRIANGLES, n_vertices, GL_UNSIGNED_INT, 0 /* indices */); 524 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements"); 525 526 /* Set result */ 527 if (verifyResults(*context)) 528 { 529 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 530 } 531 else 532 { 533 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 534 } 535 536 /* Done */ 537 return tcu::TestNode::STOP; 538} 539 540/** Fill texture with value 128 541 * 542 * @param texture_id Id of texture 543 **/ 544void ReadnPixelsTest::cleanTexture(deqp::Context& context, glw::GLuint texture_id) 545{ 546 static const GLuint height = 8; 547 static const GLuint width = 8; 548 549 const Functions& gl = context.getRenderContext().getFunctions(); 550 551 GLubyte pixels[width * height]; 552 for (GLuint i = 0; i < width * height; ++i) 553 { 554 pixels[i] = 64; 555 } 556 557 Texture::Bind(gl, texture_id, GL_TEXTURE_2D); 558 559 Texture::SubImage(gl, GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, 0 /* z */, width, height, 0 /* depth */, 560 GL_RED_INTEGER, GL_UNSIGNED_BYTE, pixels); 561 562 /* Unbind */ 563 Texture::Bind(gl, 0, GL_TEXTURE_2D); 564} 565 566/** Verifies glReadnPixels results 567 * 568 * @return true when glReadnPixels , false otherwise 569 **/ 570bool ReadnPixelsTest::verifyResults(deqp::Context& context) 571{ 572 static const GLuint height = 8; 573 static const GLuint width = 8; 574 static const GLuint pixel_size = 4 * sizeof(GLuint); 575 576 const Functions& gl = context.getRenderContext().getFunctions(); 577 578 //Valid buffer size test 579 const GLint bufSizeValid = width * height * pixel_size; 580 GLubyte pixelsValid[bufSizeValid]; 581 582 gl.readnPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, bufSizeValid, pixelsValid); 583 GLU_EXPECT_NO_ERROR(gl.getError(), "ReadnPixels"); 584 585 //Verify glReadnPixels result 586 for (unsigned int i = 0; i < width * height; ++i) 587 { 588 const size_t offset = i * pixel_size; 589 const GLuint value = *(GLuint*)(pixelsValid + offset); 590 591 if (value != 1) 592 { 593 context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid pixel value: " << value 594 << ". Offset: " << offset << tcu::TestLog::EndMessage; 595 return false; 596 } 597 } 598 599 //Invalid buffer size test 600 const GLint bufSizeInvalid = width * height * pixel_size - 1; 601 GLubyte pixelsInvalid[bufSizeInvalid]; 602 603 gl.readnPixels(0, 0, width, height, GL_RGBA_INTEGER, GL_UNSIGNED_INT, bufSizeInvalid, pixelsInvalid); 604 if (!verifyError(gl.getError(), GL_INVALID_OPERATION, "ReadnPixels [false positive]")) 605 return false; 606 607 return true; 608} 609 610/** Verify operation errors 611 * 612 * @param error OpenGL ES error code 613 * @param expectedError Expected error code 614 * @param method Method name marker 615 * 616 * @return true when error is as expected, false otherwise 617 **/ 618bool ReadnPixelsTest::verifyError(GLint error, GLint expectedError, const char* method) 619{ 620 if (error != expectedError) 621 { 622 m_testCtx.getLog() << tcu::TestLog::Message << "Test failed! " << method << " throws unexpected error [" 623 << error << "]." << tcu::TestLog::EndMessage; 624 625 return false; 626 } 627 628 return true; 629} 630 631} // RobustBufferAccessBehavior namespace 632 633RobustnessTests::RobustnessTests(tcu::TestContext& testCtx, glu::ApiType apiType) 634 : tcu::TestCaseGroup(testCtx, "robustness", 635 "Verifies API coverage and functionality of GL_KHR_robustness extension.") 636 , m_ApiType(apiType) 637{ 638} 639 640void RobustnessTests::init(void) 641{ 642 tcu::TestCaseGroup::init(); 643 644 try 645 { 646 addChild(new ResetNotificationStrategy::NoResetNotificationCase( 647 m_testCtx, "no_reset_notification", "Verifies if NO_RESET_NOTIFICATION strategy works as expected.", 648 m_ApiType)); 649 addChild(new ResetNotificationStrategy::LoseContextOnResetCase( 650 m_testCtx, "lose_context_on_reset", "Verifies if LOSE_CONTEXT_ON_RESET strategy works as expected.", 651 m_ApiType)); 652 653 addChild(new RobustBufferAccessBehavior::GetnUniformTest(m_testCtx, m_ApiType)); 654 addChild(new RobustBufferAccessBehavior::ReadnPixelsTest(m_testCtx, m_ApiType)); 655 } 656 catch (...) 657 { 658 // Destroy context. 659 tcu::TestCaseGroup::deinit(); 660 throw; 661 } 662} 663 664} // glcts namespace 665