1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2014-2016 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 21 * \brief 22 */ /*-------------------------------------------------------------------*/ 23 24 #include "esextcGeometryShaderOutput.hpp" 25 26 #include "gluContextInfo.hpp" 27 #include "glwEnums.hpp" 28 #include "glwFunctions.hpp" 29 #include "tcuTestLog.hpp" 30 31 namespace glcts 32 { 33 34 /* Shared shaders */ 35 const char* const GeometryShaderOutput::m_fragment_shader_code_white_color = "${VERSION}\n" 36 "\n" 37 "precision highp float;\n" 38 "\n" 39 "out vec4 color;\n" 40 "\n" 41 "void main()\n" 42 "{\n" 43 " color = vec4(1, 1, 1, 1);\n" 44 "}\n"; 45 46 const char* const GeometryShaderOutput::m_vertex_shader_code_two_vec4 = "${VERSION}\n" 47 "\n" 48 "precision highp float;\n" 49 "\n" 50 "out vec4 v1;\n" 51 "out vec4 v2;\n" 52 "\n" 53 "void main()\n" 54 "{\n" 55 " v1 = vec4(-0.5, -0.5, 0, 1);\n" 56 " v2 = vec4( 0.5, 0.5, 0, 1);\n" 57 "}\n"; 58 59 const char* const GeometryShaderOutput::m_vertex_shader_code_vec4_0_0_0_1 = "${VERSION}\n" 60 "\n" 61 "precision highp float;\n" 62 "\n" 63 "void main()\n" 64 "{\n" 65 " gl_Position = vec4(0, 0, 0, 1);\n" 66 "}\n"; 67 68 /* Shaders for GeometryShaderDuplicateOutputLayoutQualifierTest */ 69 const char* const GeometryShaderDuplicateOutputLayoutQualifierTest::m_geometry_shader_code = 70 "${VERSION}\n" 71 "\n" 72 "${GEOMETRY_SHADER_REQUIRE}\n" 73 "\n" 74 "layout(points) in;\n" 75 "layout(triangle_strip, max_vertices = 60) out;\n" 76 "layout(points) out;\n" 77 "\n" 78 "in vec4 v1[];\n" 79 "in vec4 v2[];\n" 80 "\n" 81 "void main()\n" 82 "{\n" 83 " gl_Position = v1[0] + vec4(-0.1, -0.1, 0, 0);\n" 84 " EmitVertex();\n" 85 " gl_Position = v1[0] + vec4(0.1, -0.1, 0, 0);\n" 86 " EmitVertex();\n" 87 " gl_Position = v1[0] + vec4(0.1, 0.1, 0, 0);\n" 88 " EmitVertex();\n" 89 " EndPrimitive();\n" 90 "\n" 91 " gl_Position = v2[0] + vec4(-0.1, -0.1, 0, 0);\n" 92 " EmitVertex();\n" 93 " gl_Position = v2[0] + vec4(-0.1, 0.1, 0, 0);\n" 94 " EmitVertex();\n" 95 " gl_Position = v2[0] + vec4(0.1, 0.1, 0, 0);\n" 96 " EmitVertex();\n" 97 " EndPrimitive();\n" 98 "}\n"; 99 100 /* Shaders for GeometryShaderDuplicateMaxVerticesLayoutQualifierTest */ 101 const char* const GeometryShaderDuplicateMaxVerticesLayoutQualifierTest::m_geometry_shader_code = 102 "${VERSION}\n" 103 "\n" 104 "${GEOMETRY_SHADER_REQUIRE}\n" 105 "\n" 106 "layout(points) in;\n" 107 "layout(triangle_strip, max_vertices = 60) out;\n" 108 "layout(max_vertices = 20) out;\n" 109 "\n" 110 "in vec4 v1[];\n" 111 "in vec4 v2[];\n" 112 "\n" 113 "void main()\n" 114 "{\n" 115 " gl_Position = v1[0] + vec4(-0.1, -0.1, 0, 0);\n" 116 " EmitVertex();\n" 117 " gl_Position = v1[0] + vec4(0.1, -0.1, 0, 0);\n" 118 " EmitVertex();\n" 119 " gl_Position = v1[0] + vec4(0.1, 0.1, 0, 0);\n" 120 " EmitVertex();\n" 121 " EndPrimitive();\n" 122 "\n" 123 " gl_Position = v2[0] + vec4(-0.1, -0.1, 0, 0);\n" 124 " EmitVertex();\n" 125 " gl_Position = v2[0] + vec4(-0.1, 0.1, 0, 0);\n" 126 " EmitVertex();\n" 127 " gl_Position = v2[0] + vec4(0.1, 0.1, 0, 0);\n" 128 " EmitVertex();\n" 129 " EndPrimitive();\n" 130 "}\n"; 131 132 /* Shaders for GeometryShaderIfVertexEmitIsDoneAtEndTest */ 133 const char* const GeometryShaderIfVertexEmitIsDoneAtEndTest::m_geometry_shader_code = 134 "${VERSION}\n" 135 "\n" 136 "${GEOMETRY_SHADER_REQUIRE}\n" 137 "\n" 138 "precision highp float;\n" 139 "\n" 140 "layout(points) in;\n" 141 "layout(triangle_strip, max_vertices = 60) out;\n" 142 "\n" 143 "in vec4 v1[];\n" 144 "\n" 145 "void main()\n" 146 "{\n" 147 " gl_Position = vec4(-1, -1, 0, 1);\n" 148 " EmitVertex();\n" 149 " gl_Position = vec4(-1, 1, 0, 1);\n" 150 " EmitVertex();\n" 151 " gl_Position = vec4(1, 1, 0, 1);\n" 152 " EndPrimitive();\n" 153 "}\n"; 154 155 /* Shaders for GeometryShaderMissingEndPrimitiveCallTest */ 156 const char* const GeometryShaderMissingEndPrimitiveCallTest::m_geometry_shader_code = 157 "${VERSION}\n" 158 "\n" 159 "${GEOMETRY_SHADER_REQUIRE}\n" 160 "\n" 161 "layout(points) in;\n" 162 "layout(triangle_strip, max_vertices = 60) out;\n" 163 "\n" 164 "void main()\n" 165 "{\n" 166 " gl_Position = vec4(-1, -1.004, 0, 1);\n" 167 " EmitVertex();\n" 168 " gl_Position = vec4(-1, 1, 0, 1);\n" 169 " EmitVertex();\n" 170 " gl_Position = vec4(1.004, 1, 0, 1);\n" 171 " EmitVertex();\n" 172 "}\n"; 173 174 /* Shaders for GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest */ 175 const char* const GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest::m_geometry_shader_code = 176 "${VERSION}\n" 177 "\n" 178 "${GEOMETRY_SHADER_REQUIRE}\n" 179 "${GEOMETRY_POINT_SIZE_ENABLE}\n" 180 "\n" 181 "layout(points) in;\n" 182 "layout(points, max_vertices = 1) out;\n" 183 "\n" 184 "void main()\n" 185 "{\n" 186 " gl_Position = vec4(-1, -1, 0, 1);\n" 187 " gl_PointSize = 2.0f;\n" 188 " EmitVertex();\n" 189 "}\n"; 190 191 /* Definitions used by all test cases */ 192 #define TEXTURE_HEIGHT (16) 193 #define TEXTURE_PIXEL_SIZE (4) 194 #define TEXTURE_WIDTH (16) 195 196 /** Constructor 197 * 198 * @param context Test context 199 * @param name Test case's name 200 * @param description Test case's description 201 **/ 202 GeometryShaderOutput::GeometryShaderOutput(Context& context, const ExtParameters& extParams, const char* name, 203 const char* description) 204 : TestCaseBase(context, extParams, name, description) 205 { 206 /* Left blank on purpose */ 207 } 208 209 /** Constructor 210 * 211 * @param context Test context 212 * @param name Test case's name 213 * @param description Test case's desricption 214 **/ 215 GeometryShaderDuplicateOutputLayoutQualifierTest::GeometryShaderDuplicateOutputLayoutQualifierTest( 216 Context& context, const ExtParameters& extParams, const char* name, const char* description) 217 : GeometryShaderOutput(context, extParams, name, description) 218 { 219 /* Nothing to be done here */ 220 } 221 222 /** Executes the test. 223 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 224 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 225 * Note the function throws exception should an error occur! 226 **/ 227 tcu::TestCase::IterateResult GeometryShaderDuplicateOutputLayoutQualifierTest::iterate() 228 { 229 if (!m_is_geometry_shader_extension_supported) 230 { 231 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 232 } 233 234 /* Verify the program does not build. */ 235 bool result = doesProgramBuild(1, &m_fragment_shader_code_white_color, 1, &m_geometry_shader_code, 1, 236 &m_vertex_shader_code_two_vec4); 237 238 if (false == result) 239 { 240 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 241 } 242 else 243 { 244 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid program was linked successfully." 245 << tcu::TestLog::EndMessage; 246 247 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 248 } 249 250 return STOP; 251 } 252 253 /** Constructor 254 * 255 * @param context Test context 256 * @param name Test case's name 257 * @param description Test case's desricption 258 **/ 259 GeometryShaderDuplicateMaxVerticesLayoutQualifierTest::GeometryShaderDuplicateMaxVerticesLayoutQualifierTest( 260 Context& context, const ExtParameters& extParams, const char* name, const char* description) 261 : GeometryShaderOutput(context, extParams, name, description) 262 { 263 /* Nothing to be done here */ 264 } 265 266 /** Executes the test. 267 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 268 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 269 * Note the function throws exception should an error occur! 270 **/ 271 tcu::TestCase::IterateResult GeometryShaderDuplicateMaxVerticesLayoutQualifierTest::iterate() 272 { 273 if (!m_is_geometry_shader_extension_supported) 274 { 275 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 276 } 277 278 /* Verify the program does not build. */ 279 bool result = doesProgramBuild(1, &m_fragment_shader_code_white_color, 1, &m_geometry_shader_code, 1, 280 &m_vertex_shader_code_two_vec4); 281 282 if (false == result) 283 { 284 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 285 } 286 else 287 { 288 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid program was linked successfully." 289 << tcu::TestLog::EndMessage; 290 291 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 292 } 293 294 return STOP; 295 } 296 297 /** Constructor 298 * 299 * @param context Test context 300 * @param name Test case's name 301 * @param description Test case's desricption 302 * @param geometry_shader_code Code of geometry shader 303 **/ 304 GeometryShaderOutputRenderingBase::GeometryShaderOutputRenderingBase(Context& context, const ExtParameters& extParams, 305 const char* name, const char* description, 306 const char* geometry_shader_code) 307 : GeometryShaderOutput(context, extParams, name, description) 308 , m_geometry_shader_code(geometry_shader_code) 309 , m_program_object_id(0) 310 , m_vertex_shader_id(0) 311 , m_fragment_shader_id(0) 312 , m_geometry_shader_id(0) 313 , m_vao_id(0) 314 , m_fbo_id(0) 315 , m_color_tex_id(0) 316 { 317 /* Left blank on purpose */ 318 } 319 320 /** Initialize test case 321 * 322 **/ 323 void GeometryShaderOutputRenderingBase::initTest() 324 { 325 if (!m_is_geometry_shader_extension_supported) 326 { 327 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 328 } 329 330 /* GL functions */ 331 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 332 333 /* Create shader objects */ 334 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 335 m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 336 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 337 338 /* Create program object */ 339 m_program_object_id = gl.createProgram(); 340 341 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object"); 342 343 /* Build the program object */ 344 if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1, &m_fragment_shader_code_white_color, 345 m_geometry_shader_id, 1, &m_geometry_shader_code, m_vertex_shader_id, 1, 346 &m_vertex_shader_code_vec4_0_0_0_1)) 347 { 348 TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader"); 349 } 350 351 /* Set up texture object and a FBO */ 352 gl.genTextures(1, &m_color_tex_id); 353 gl.genFramebuffers(1, &m_fbo_id); 354 355 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer"); 356 357 if (false == 358 setupFramebufferWithTextureAsAttachment(m_fbo_id, m_color_tex_id, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT)) 359 { 360 TCU_FAIL("Failed to setup framebuffer"); 361 } 362 363 /* Set up a vertex array object */ 364 gl.genVertexArrays(1, &m_vao_id); 365 gl.bindVertexArray(m_vao_id); 366 367 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 368 { 369 gl.enable(GL_PROGRAM_POINT_SIZE); 370 } 371 372 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object"); 373 } 374 375 /** Executes the test. 376 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 377 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 378 * Note the function throws exception should an error occur! 379 **/ 380 tcu::TestCase::IterateResult GeometryShaderOutputRenderingBase::iterate() 381 { 382 initTest(); 383 384 /* Variables used for image verification purposes */ 385 unsigned char result_image[TEXTURE_HEIGHT * TEXTURE_WIDTH * TEXTURE_PIXEL_SIZE]; 386 387 /* GL functions */ 388 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 389 390 /* Render */ 391 gl.useProgram(m_program_object_id); 392 393 gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */); 394 gl.clear(GL_COLOR_BUFFER_BIT); 395 396 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer"); 397 398 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */); 399 400 GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed"); 401 402 /* Extract image from FBO */ 403 gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_image); 404 405 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer"); 406 407 /* Run verification */ 408 if (true == verifyResult(result_image, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_PIXEL_SIZE)) 409 { 410 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 411 } 412 else 413 { 414 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 415 } 416 417 return STOP; 418 } 419 420 /** Deinitialize test case 421 * 422 **/ 423 void GeometryShaderOutputRenderingBase::deinit() 424 { 425 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 426 427 /* Reset OpenGL ES state */ 428 gl.useProgram(0); 429 gl.bindVertexArray(0); 430 gl.bindTexture(GL_TEXTURE_2D, 0); 431 gl.bindFramebuffer(GL_FRAMEBUFFER, 0); 432 if (!glu::isContextTypeES(m_context.getRenderContext().getType())) 433 { 434 gl.disable(GL_PROGRAM_POINT_SIZE); 435 } 436 437 if (m_program_object_id != 0) 438 { 439 gl.deleteProgram(m_program_object_id); 440 } 441 442 if (m_fragment_shader_id != 0) 443 { 444 gl.deleteShader(m_fragment_shader_id); 445 } 446 447 if (m_geometry_shader_id != 0) 448 { 449 gl.deleteShader(m_geometry_shader_id); 450 } 451 452 if (m_vertex_shader_id != 0) 453 { 454 gl.deleteShader(m_vertex_shader_id); 455 } 456 457 if (m_vao_id != 0) 458 { 459 gl.deleteVertexArrays(1, &m_vao_id); 460 } 461 462 if (m_color_tex_id != 0) 463 { 464 gl.deleteTextures(1, &m_color_tex_id); 465 } 466 467 if (m_fbo_id != 0) 468 { 469 gl.deleteFramebuffers(1, &m_fbo_id); 470 } 471 472 /* Release base class */ 473 TestCaseBase::deinit(); 474 } 475 476 /** Constructor 477 * 478 * @param context Test context 479 * @param name Test case's name 480 * @param description Test case's desricption 481 **/ 482 GeometryShaderIfVertexEmitIsDoneAtEndTest::GeometryShaderIfVertexEmitIsDoneAtEndTest(Context& context, 483 const ExtParameters& extParams, 484 const char* name, 485 const char* description) 486 : GeometryShaderOutputRenderingBase(context, extParams, name, description, m_geometry_shader_code) 487 { 488 /* Left blank on purpose */ 489 } 490 491 /** Verifies result of draw call 492 * 493 * @param result_image Image data 494 * @param width Image width 495 * @param height Image height 496 * @param pixel_size Size of single pixel in bytes 497 * 498 * @return true if test succeded 499 * false if the test failed 500 * Note the function throws exception should an error occur! 501 **/ 502 bool GeometryShaderIfVertexEmitIsDoneAtEndTest::verifyResult(const unsigned char* result_image, unsigned int width, 503 unsigned int height, unsigned int pixel_size) const 504 { 505 /* Check if the data was modified during the rendering process */ 506 for (unsigned int y = 0; y < height; ++y) 507 { 508 for (unsigned int x = 0; x < width; ++x) 509 { 510 if (false == comparePixel(result_image, x, y, width, height, pixel_size)) 511 { 512 m_testCtx.getLog() << tcu::TestLog::Message 513 << "Vertex emitted without a corresponding EmitVertex() call made" 514 << tcu::TestLog::EndMessage; 515 516 return false; 517 } 518 } 519 } 520 521 /* Done */ 522 return true; 523 } 524 525 /** Constructor 526 * 527 * @param context Test context 528 * @param name Test case's name 529 * @param description Test case's desricption 530 **/ 531 GeometryShaderMissingEndPrimitiveCallTest::GeometryShaderMissingEndPrimitiveCallTest(Context& context, 532 const ExtParameters& extParams, 533 const char* name, 534 const char* description) 535 : GeometryShaderOutputRenderingBase(context, extParams, name, description, m_geometry_shader_code) 536 { 537 /* Left blank on purpose */ 538 } 539 540 /** Verifies result of draw call 541 * 542 * @param result_image Image data 543 * @param width Image width 544 * @param height Image height 545 * @param pixel_size Size of single pixel in bytes 546 * 547 * @return true if test succeded 548 * false if the test failed 549 **/ 550 bool GeometryShaderMissingEndPrimitiveCallTest::verifyResult(const unsigned char* result_image, unsigned int width, 551 unsigned int height, unsigned int pixel_size) const 552 { 553 /* Image size */ 554 const unsigned int left = 0; 555 const unsigned int right = width - 1; 556 const unsigned int bottom = 0; 557 const unsigned int top = height - 1; 558 559 /* Verification */ 560 if ((true == comparePixel(result_image, left, bottom, width, height, pixel_size, 255, 255, 255, 255)) && 561 (true == comparePixel(result_image, left, top, width, height, pixel_size, 255, 255, 255, 255)) && 562 (true == comparePixel(result_image, right, top, width, height, pixel_size, 255, 255, 255, 255)) && 563 (true == comparePixel(result_image, right, bottom, width, height, pixel_size, 0, 0, 0, 0))) 564 { 565 return true; 566 } 567 else 568 { 569 m_testCtx.getLog() << tcu::TestLog::Message << "EndPrimitive() is not called at the end of geometry shader" 570 << tcu::TestLog::EndMessage; 571 572 return false; 573 } 574 } 575 576 /** Constructor 577 * 578 * @param context Test context 579 * @param name Test case's name 580 * @param description Test case's desricption 581 **/ 582 GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest:: 583 GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest(Context& context, const ExtParameters& extParams, 584 const char* name, const char* description) 585 : GeometryShaderOutputRenderingBase(context, extParams, name, description, m_geometry_shader_code) 586 { 587 /* Left blank on purpose */ 588 } 589 590 /** Executes the test. 591 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 592 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 593 * Note the function throws exception should an error occur! 594 **/ 595 tcu::TestCase::IterateResult GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest::iterate() 596 { 597 if (!m_is_geometry_shader_point_size_supported) 598 { 599 throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__); 600 } 601 602 return GeometryShaderOutputRenderingBase::iterate(); 603 } 604 605 /** Verifies result of draw call 606 * 607 * @param result_image Image data 608 * @param width Image width 609 * @param height Image height 610 * @param pixel_size Size of single pixel in bytes 611 * 612 * @return true if test succeded 613 * false if the test failed 614 * Note the function throws exception should an error occur! 615 **/ 616 bool GeometryShaderMissingEndPrimitiveCallForSinglePrimitiveTest::verifyResult(const unsigned char* result_image, 617 unsigned int width, unsigned int height, 618 unsigned int pixel_size) const 619 { 620 /* Image size */ 621 const unsigned int left = 0; 622 const unsigned int right = width - 1; 623 const unsigned int bottom = 0; 624 const unsigned int top = height - 1; 625 626 /* Verification */ 627 if ((true == comparePixel(result_image, left, bottom, width, height, pixel_size, 255, 255, 255, 255)) && 628 (true == comparePixel(result_image, left, top, width, height, pixel_size, 0, 0, 0, 0)) && 629 (true == comparePixel(result_image, right, top, width, height, pixel_size, 0, 0, 0, 0)) && 630 (true == comparePixel(result_image, right, bottom, width, height, pixel_size, 0, 0, 0, 0))) 631 { 632 return true; 633 } 634 else 635 { 636 m_testCtx.getLog() << tcu::TestLog::Message << "EndPrimitive() is not done for a single primitive" 637 << tcu::TestLog::EndMessage; 638 639 return false; 640 } 641 } 642 643 } // namespace glcts 644