1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 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 Functional rasterization tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fRasterizationTests.hpp" 25 #include "tcuRasterizationVerifier.hpp" 26 #include "tcuSurface.hpp" 27 #include "tcuRenderTarget.hpp" 28 #include "tcuVectorUtil.hpp" 29 #include "tcuStringTemplate.hpp" 30 #include "tcuResultCollector.hpp" 31 #include "gluShaderProgram.hpp" 32 #include "gluRenderContext.hpp" 33 #include "gluPixelTransfer.hpp" 34 #include "gluStrUtil.hpp" 35 #include "deStringUtil.hpp" 36 #include "deRandom.hpp" 37 #include "glwFunctions.hpp" 38 #include "glwEnums.hpp" 39 40 #include <vector> 41 42 namespace deqp 43 { 44 namespace gles2 45 { 46 namespace Functional 47 { 48 namespace 49 { 50 51 using tcu::RasterizationArguments; 52 using tcu::TriangleSceneSpec; 53 using tcu::PointSceneSpec; 54 using tcu::LineSceneSpec; 55 using tcu::LineInterpolationMethod; 56 57 static const char* const s_shaderVertexTemplate = "attribute highp vec4 a_position;\n" 58 "attribute highp vec4 a_color;\n" 59 "varying highp vec4 v_color;\n" 60 "uniform highp float u_pointSize;\n" 61 "void main ()\n" 62 "{\n" 63 " gl_Position = a_position;\n" 64 " gl_PointSize = u_pointSize;\n" 65 " v_color = a_color;\n" 66 "}\n"; 67 static const char* const s_shaderFragmentTemplate = "varying mediump vec4 v_color;\n" 68 "void main ()\n" 69 "{\n" 70 " gl_FragColor = v_color;\n" 71 "}\n"; 72 enum InterpolationCaseFlags 73 { 74 INTERPOLATIONFLAGS_NONE = 0, 75 INTERPOLATIONFLAGS_PROJECTED = (1 << 1), 76 }; 77 78 enum PrimitiveWideness 79 { 80 PRIMITIVEWIDENESS_NARROW = 0, 81 PRIMITIVEWIDENESS_WIDE, 82 83 PRIMITIVEWIDENESS_LAST 84 }; 85 86 class BaseRenderingCase : public TestCase 87 { 88 public: 89 BaseRenderingCase (Context& context, const char* name, const char* desc, int renderSize = 256); 90 ~BaseRenderingCase (void); 91 virtual void init (void); 92 void deinit (void); 93 94 protected: 95 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType); 96 void drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, glw::GLenum primitiveType); 97 98 const int m_renderSize; 99 int m_numSamples; 100 int m_subpixelBits; 101 float m_pointSize; 102 float m_lineWidth; 103 104 glu::ShaderProgram* m_shader; 105 }; 106 107 BaseRenderingCase::BaseRenderingCase (Context& context, const char* name, const char* desc, int renderSize) 108 : TestCase (context, name, desc) 109 , m_renderSize (renderSize) 110 , m_numSamples (-1) 111 , m_subpixelBits (-1) 112 , m_pointSize (1.0f) 113 , m_lineWidth (1.0f) 114 , m_shader (DE_NULL) 115 { 116 } 117 118 BaseRenderingCase::~BaseRenderingCase (void) 119 { 120 deinit(); 121 } 122 123 void BaseRenderingCase::init (void) 124 { 125 const int width = m_context.getRenderTarget().getWidth(); 126 const int height = m_context.getRenderTarget().getHeight(); 127 128 // Requirements 129 130 if (width < m_renderSize || height < m_renderSize) 131 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_renderSize) + "x" + de::toString(m_renderSize)); 132 133 if (m_lineWidth != 1.0f) 134 { 135 float range[2] = { 0.0f, 0.0f }; 136 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range); 137 138 if (m_lineWidth < range[0] || m_lineWidth > range[1]) 139 throw tcu::NotSupportedError(std::string("Support for line width ") + de::toString(m_lineWidth) + " is required."); 140 141 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage; 142 } 143 144 if (m_pointSize != 1.0f) 145 { 146 float range[2] = { 0.0f, 0.0f }; 147 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range); 148 149 if (m_pointSize < range[0] || m_pointSize > range[1]) 150 throw tcu::NotSupportedError(std::string("Support for point size ") + de::toString(m_pointSize) + " is required."); 151 152 m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage; 153 } 154 155 // Query info 156 157 m_numSamples = m_context.getRenderTarget().getNumSamples(); 158 m_context.getRenderContext().getFunctions().getIntegerv(GL_SUBPIXEL_BITS, &m_subpixelBits); 159 160 m_testCtx.getLog() << tcu::TestLog::Message << "Sample count = " << m_numSamples << tcu::TestLog::EndMessage; 161 m_testCtx.getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage; 162 163 // Gen shader 164 165 { 166 tcu::StringTemplate vertexSource (s_shaderVertexTemplate); 167 tcu::StringTemplate fragmentSource (s_shaderFragmentTemplate); 168 std::map<std::string, std::string> params; 169 170 m_shader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource.specialize(params)) << glu::FragmentSource(fragmentSource.specialize(params))); 171 if (!m_shader->isOk()) 172 throw tcu::TestError("could not create shader"); 173 } 174 } 175 176 void BaseRenderingCase::deinit (void) 177 { 178 if (m_shader) 179 { 180 delete m_shader; 181 m_shader = DE_NULL; 182 } 183 } 184 185 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType) 186 { 187 // default to color white 188 const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 189 190 drawPrimitives(result, vertexData, colorData, primitiveType); 191 } 192 193 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& colorData, glw::GLenum primitiveType) 194 { 195 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 196 const glw::GLint positionLoc = gl.getAttribLocation(m_shader->getProgram(), "a_position"); 197 const glw::GLint colorLoc = gl.getAttribLocation(m_shader->getProgram(), "a_color"); 198 const glw::GLint pointSizeLoc = gl.getUniformLocation(m_shader->getProgram(), "u_pointSize"); 199 200 gl.clearColor (0, 0, 0, 1); 201 gl.clear (GL_COLOR_BUFFER_BIT); 202 gl.viewport (0, 0, m_renderSize, m_renderSize); 203 gl.useProgram (m_shader->getProgram()); 204 gl.enableVertexAttribArray (positionLoc); 205 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertexData[0]); 206 gl.enableVertexAttribArray (colorLoc); 207 gl.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, 0, &colorData[0]); 208 gl.uniform1f (pointSizeLoc, m_pointSize); 209 gl.lineWidth (m_lineWidth); 210 gl.drawArrays (primitiveType, 0, (glw::GLsizei)vertexData.size()); 211 gl.disableVertexAttribArray (colorLoc); 212 gl.disableVertexAttribArray (positionLoc); 213 gl.useProgram (0); 214 gl.finish (); 215 GLU_EXPECT_NO_ERROR (gl.getError(), "draw primitives"); 216 217 glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess()); 218 } 219 220 class BaseTriangleCase : public BaseRenderingCase 221 { 222 public: 223 BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType); 224 ~BaseTriangleCase (void); 225 IterateResult iterate (void); 226 227 private: 228 virtual void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL; 229 230 int m_iteration; 231 const int m_iterationCount; 232 const glw::GLenum m_primitiveDrawType; 233 bool m_allIterationsPassed; 234 }; 235 236 BaseTriangleCase::BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType) 237 : BaseRenderingCase (context, name, desc) 238 , m_iteration (0) 239 , m_iterationCount (3) 240 , m_primitiveDrawType (primitiveDrawType) 241 , m_allIterationsPassed (true) 242 { 243 } 244 245 BaseTriangleCase::~BaseTriangleCase (void) 246 { 247 } 248 249 BaseTriangleCase::IterateResult BaseTriangleCase::iterate (void) 250 { 251 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 252 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription); 253 tcu::Surface resultImage (m_renderSize, m_renderSize); 254 std::vector<tcu::Vec4> drawBuffer; 255 std::vector<TriangleSceneSpec::SceneTriangle> triangles; 256 257 generateTriangles(m_iteration, drawBuffer, triangles); 258 259 // draw image 260 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType); 261 262 // compare 263 { 264 bool compareOk; 265 RasterizationArguments args; 266 TriangleSceneSpec scene; 267 268 args.numSamples = m_numSamples; 269 args.subpixelBits = m_subpixelBits; 270 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits; 271 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits; 272 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits; 273 274 scene.triangles.swap(triangles); 275 276 compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog()); 277 278 if (!compareOk) 279 m_allIterationsPassed = false; 280 } 281 282 // result 283 if (++m_iteration == m_iterationCount) 284 { 285 if (m_allIterationsPassed) 286 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 287 else 288 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization"); 289 290 return STOP; 291 } 292 else 293 return CONTINUE; 294 } 295 296 class BaseLineCase : public BaseRenderingCase 297 { 298 public: 299 BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness); 300 ~BaseLineCase (void); 301 IterateResult iterate (void); 302 303 private: 304 virtual void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL; 305 306 int m_iteration; 307 const int m_iterationCount; 308 const glw::GLenum m_primitiveDrawType; 309 const PrimitiveWideness m_primitiveWideness; 310 bool m_allIterationsPassed; 311 bool m_multisampleRelaxationRequired; 312 313 static const float s_wideSize; 314 }; 315 316 const float BaseLineCase::s_wideSize = 5.0f; 317 318 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness) 319 : BaseRenderingCase (context, name, desc) 320 , m_iteration (0) 321 , m_iterationCount (3) 322 , m_primitiveDrawType (primitiveDrawType) 323 , m_primitiveWideness (wideness) 324 , m_allIterationsPassed (true) 325 , m_multisampleRelaxationRequired (false) 326 { 327 DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST); 328 m_lineWidth = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f); 329 } 330 331 BaseLineCase::~BaseLineCase (void) 332 { 333 } 334 335 BaseLineCase::IterateResult BaseLineCase::iterate (void) 336 { 337 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 338 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription); 339 tcu::Surface resultImage (m_renderSize, m_renderSize); 340 std::vector<tcu::Vec4> drawBuffer; 341 std::vector<LineSceneSpec::SceneLine> lines; 342 343 // last iteration, max out size 344 if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE && 345 m_iteration+1 == m_iterationCount) 346 { 347 float range[2] = { 0.0f, 0.0f }; 348 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range); 349 350 m_lineWidth = range[1]; 351 } 352 353 // gen data 354 generateLines(m_iteration, drawBuffer, lines); 355 356 // draw image 357 drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType); 358 359 // compare 360 { 361 bool compareOk; 362 RasterizationArguments args; 363 LineSceneSpec scene; 364 365 args.numSamples = m_numSamples; 366 args.subpixelBits = m_subpixelBits; 367 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits; 368 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits; 369 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits; 370 371 scene.lines.swap(lines); 372 scene.lineWidth = m_lineWidth; 373 374 compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog()); 375 376 // multisampled wide lines might not be supported 377 if (scene.lineWidth != 1.0f && m_numSamples > 1 && !compareOk) 378 { 379 m_multisampleRelaxationRequired = true; 380 compareOk = true; 381 } 382 383 if (!compareOk) 384 m_allIterationsPassed = false; 385 } 386 387 // result 388 if (++m_iteration == m_iterationCount) 389 { 390 if (m_allIterationsPassed && m_multisampleRelaxationRequired) 391 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Rasterization of multisampled wide lines failed"); 392 else if (m_allIterationsPassed) 393 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 394 else 395 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization"); 396 397 return STOP; 398 } 399 else 400 return CONTINUE; 401 } 402 403 class PointCase : public BaseRenderingCase 404 { 405 public: 406 PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness); 407 ~PointCase (void); 408 IterateResult iterate (void); 409 410 private: 411 void generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints); 412 413 int m_iteration; 414 const int m_iterationCount; 415 const PrimitiveWideness m_primitiveWideness; 416 bool m_allIterationsPassed; 417 418 static const float s_wideSize; 419 }; 420 421 const float PointCase::s_wideSize = 10.0f; 422 423 PointCase::PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness) 424 : BaseRenderingCase (context, name, desc) 425 , m_iteration (0) 426 , m_iterationCount (3) 427 , m_primitiveWideness (wideness) 428 , m_allIterationsPassed (true) 429 { 430 m_pointSize = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f); 431 } 432 433 PointCase::~PointCase (void) 434 { 435 } 436 437 PointCase::IterateResult PointCase::iterate (void) 438 { 439 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 440 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription); 441 tcu::Surface resultImage (m_renderSize, m_renderSize); 442 std::vector<tcu::Vec4> drawBuffer; 443 std::vector<PointSceneSpec::ScenePoint> points; 444 445 // last iteration, max out size 446 if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE && 447 m_iteration+1 == m_iterationCount) 448 { 449 float range[2] = { 0.0f, 0.0f }; 450 m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range); 451 452 m_pointSize = range[1]; 453 } 454 455 // gen data 456 generatePoints(m_iteration, drawBuffer, points); 457 458 // draw image 459 drawPrimitives(resultImage, drawBuffer, GL_POINTS); 460 461 // compare 462 { 463 bool compareOk; 464 RasterizationArguments args; 465 PointSceneSpec scene; 466 467 args.numSamples = m_numSamples; 468 args.subpixelBits = m_subpixelBits; 469 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits; 470 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits; 471 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits; 472 473 scene.points.swap(points); 474 475 compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_testCtx.getLog()); 476 477 if (!compareOk) 478 m_allIterationsPassed = false; 479 } 480 481 // result 482 if (++m_iteration == m_iterationCount) 483 { 484 if (m_allIterationsPassed) 485 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 486 else 487 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization"); 488 489 return STOP; 490 } 491 else 492 return CONTINUE; 493 } 494 495 void PointCase::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints) 496 { 497 outData.resize(6); 498 499 switch (iteration) 500 { 501 case 0: 502 // \note: these values are chosen arbitrarily 503 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f); 504 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 505 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f); 506 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 507 outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f); 508 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f); 509 break; 510 511 case 1: 512 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 513 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 514 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 515 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 516 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 517 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f); 518 break; 519 520 case 2: 521 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 522 outData[1] = tcu::Vec4( 0.3f, -0.9f, 0.0f, 1.0f); 523 outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f); 524 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f); 525 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 526 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f); 527 break; 528 } 529 530 outPoints.resize(outData.size()); 531 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx) 532 { 533 outPoints[pointNdx].position = outData[pointNdx]; 534 outPoints[pointNdx].pointSize = m_pointSize; 535 } 536 537 // log 538 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << m_pointSize << ")" << tcu::TestLog::EndMessage; 539 for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx) 540 m_testCtx.getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage; 541 } 542 543 class PointSizeClampedTest : public BaseRenderingCase 544 { 545 public: 546 PointSizeClampedTest (Context& context, const char* name, const char* desc) 547 : BaseRenderingCase (context, name, desc) 548 { 549 } 550 551 IterateResult iterate () 552 { 553 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 554 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 555 556 // Tests that point sizes (written to gl_PointSize) are clamped, 557 // before rasterization, to the ALIASED_POINT_SIZE_RANGE 558 // given by the implementation. 559 static const int fboHeight = 4; 560 static const int testAreaWidth = 4; 561 static const int testAreaWidthWithMargin = testAreaWidth + 4; 562 static const float pointRadiusOverage = 8; 563 int fboWidth = 0; 564 int maxPointDiameter = 0; 565 { 566 int maxRenderbufferSize = 0; 567 int maxViewportDims[2] = {}; 568 gl.getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &maxRenderbufferSize); 569 gl.getIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDims); 570 int maxFboWidth = std::min(maxRenderbufferSize, maxViewportDims[0]); 571 572 float pointSizeRange[2] = {}; 573 gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange); 574 m_testCtx.getLog() << tcu::TestLog::Message 575 << "GL_ALIASED_POINT_SIZE_RANGE is [" << pointSizeRange[0] << ", " << pointSizeRange[1] << "]" 576 << tcu::TestLog::EndMessage; 577 // Typically (in the correct case), maxPointDiameter is an odd integer. 578 maxPointDiameter = (int) pointSizeRange[1]; 579 // maxPointRadius is inclusive of the center point. 580 int maxPointRadius = (maxPointDiameter + 1) / 2; 581 if (maxPointRadius > maxFboWidth - testAreaWidthWithMargin) 582 { 583 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "max framebuffer size isn't large enough to test max point size"); 584 return STOP; 585 } 586 fboWidth = maxPointRadius + testAreaWidthWithMargin; 587 // Round up to the nearest multiple of 2: 588 fboWidth = ((fboWidth + 1) / 2) * 2; 589 } 590 float pointSize = ((float) maxPointDiameter) + pointRadiusOverage * 2; 591 TCU_CHECK(gl.getError() == GL_NO_ERROR); 592 593 m_testCtx.getLog() << tcu::TestLog::Message 594 << "Testing with pointSize = " << pointSize 595 << ", fboWidth = " << fboWidth 596 << tcu::TestLog::EndMessage; 597 598 // Create a framebuffer that is (fboWidth)x(fboHeight), cleared to green: 599 // +---------------------------+ 600 // |ggggggggggggggggggggggggggg| 601 // +---------------------------+ 602 gl.viewport(0, 0, fboWidth, fboHeight); 603 deUint32 fbo = 0; 604 gl.genFramebuffers(1, &fbo); 605 gl.bindFramebuffer(GL_FRAMEBUFFER, fbo); 606 deUint32 rbo = 0; 607 gl.genRenderbuffers(1, &rbo); 608 gl.bindRenderbuffer(GL_RENDERBUFFER, rbo); 609 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, fboWidth, fboHeight); 610 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); 611 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 612 { 613 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "couldn't complete a framebuffer suitable to test max point size"); 614 return STOP; 615 } 616 gl.clearColor(0.0f, 1.0f, 0.0f, 1.0f); 617 gl.clear(GL_COLOR_BUFFER_BIT); 618 TCU_CHECK(gl.getError() == GL_NO_ERROR); 619 620 // (Framebuffer is still bound.) 621 622 // Draw a red point, with size pointSize, at the far right: 623 // +---------------------------+ 624 // |ggggggggRRRRRRRRRRRRRRRRRRR| 625 // +---------------------------+ 626 // x point center 627 // ^^^^^^^^^^^^^^^^^^^^^^^^^^^ fboWidth 628 // ^^^^ testAreaWidth = 4 (this is the area that's tested) 629 // ^^^^^^^^ testAreaWidthWithMargin = 8 (extra 4 pixels for tolerance) 630 // ^^^^^^^^^^^^^^^^^^x^^^^^^^^^^^^^^^^^^ maxPointDiameter = 37 631 // ^^^^^^^^ ^^^^^^^^ pointRadiusOverage = 8 * 2 632 // ^^^^^^^^^^^^^^^^^^^^^^^^^^x^^^^^^^^^^^^^^^^^^^^^^^^^^ pointSize = 53 633 // ^^^^^^^^^^^^^^^^^^^ area of resulting draw, if the size is clamped properly = 19 634 { 635 const glw::GLint positionLoc = gl.getAttribLocation(m_shader->getProgram(), "a_position"); 636 const glw::GLint colorLoc = gl.getAttribLocation(m_shader->getProgram(), "a_color"); 637 const glw::GLint pointSizeLoc = gl.getUniformLocation(m_shader->getProgram(), "u_pointSize"); 638 static const float position[] = {1.0f, 0.0f, 0.0f, 1.0f}; 639 static const float color[] = {1.0f, 0.0f, 0.0f, 1.0f}; 640 gl.useProgram(m_shader->getProgram()); 641 gl.enableVertexAttribArray(positionLoc); 642 gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, position); 643 gl.enableVertexAttribArray(colorLoc); 644 gl.vertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, color); 645 gl.uniform1f(pointSizeLoc, pointSize); 646 gl.drawArrays(GL_POINTS, 0, 1); 647 gl.disableVertexAttribArray(colorLoc); 648 gl.disableVertexAttribArray(positionLoc); 649 gl.useProgram(0); 650 TCU_CHECK(gl.getError() == GL_NO_ERROR); 651 } 652 653 // And test the resulting draw (the test area should still be green). 654 deUint32 pixels[testAreaWidth * fboHeight] = {}; 655 gl.readPixels(0, 0, testAreaWidth, fboHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 656 TCU_CHECK(gl.getError() == GL_NO_ERROR); 657 658 const tcu::RGBA threshold(12, 12, 12, 12); 659 for (deUint32 y = 0; y < fboHeight; ++y) 660 { 661 for (deUint32 x = 0; x < testAreaWidth; ++x) 662 { 663 tcu::RGBA color(pixels[y * testAreaWidth + x]); 664 TCU_CHECK(compareThreshold(color, tcu::RGBA::green(), threshold)); 665 } 666 } 667 668 return STOP; 669 } 670 }; 671 672 class TrianglesCase : public BaseTriangleCase 673 { 674 public: 675 TrianglesCase (Context& context, const char* name, const char* desc); 676 ~TrianglesCase (void); 677 678 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles); 679 }; 680 681 TrianglesCase::TrianglesCase (Context& context, const char* name, const char* desc) 682 : BaseTriangleCase(context, name, desc, GL_TRIANGLES) 683 { 684 } 685 686 TrianglesCase::~TrianglesCase (void) 687 { 688 689 } 690 691 void TrianglesCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) 692 { 693 outData.resize(6); 694 695 switch (iteration) 696 { 697 case 0: 698 // \note: these values are chosen arbitrarily 699 outData[0] = tcu::Vec4( 0.2f, 0.8f, 0.0f, 1.0f); 700 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 701 outData[2] = tcu::Vec4( 0.5f, 0.3f, 0.0f, 1.0f); 702 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 703 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f); 704 outData[5] = tcu::Vec4(-0.4f, 0.2f, 0.0f, 1.0f); 705 break; 706 707 case 1: 708 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 709 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 710 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 711 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 712 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 713 outData[5] = tcu::Vec4( 0.4f, 1.2f, 0.0f, 1.0f); 714 break; 715 716 case 2: 717 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 718 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 719 outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f); 720 outData[3] = tcu::Vec4(-0.11f, 0.2f, 0.0f, 1.0f); 721 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 722 outData[5] = tcu::Vec4( -0.4f, 0.4f, 0.0f, 1.0f); 723 break; 724 } 725 726 outTriangles.resize(2); 727 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false; 728 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false; 729 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false; 730 731 outTriangles[1].positions[0] = outData[3]; outTriangles[1].sharedEdge[0] = false; 732 outTriangles[1].positions[1] = outData[4]; outTriangles[1].sharedEdge[1] = false; 733 outTriangles[1].positions[2] = outData[5]; outTriangles[1].sharedEdge[2] = false; 734 735 // log 736 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage; 737 for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx) 738 { 739 m_testCtx.getLog() 740 << tcu::TestLog::Message 741 << "Triangle " << (triangleNdx+1) << ":" 742 << "\n\t" << outTriangles[triangleNdx].positions[0] 743 << "\n\t" << outTriangles[triangleNdx].positions[1] 744 << "\n\t" << outTriangles[triangleNdx].positions[2] 745 << tcu::TestLog::EndMessage; 746 } 747 } 748 749 class TriangleStripCase : public BaseTriangleCase 750 { 751 public: 752 TriangleStripCase (Context& context, const char* name, const char* desc); 753 754 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles); 755 }; 756 757 TriangleStripCase::TriangleStripCase (Context& context, const char* name, const char* desc) 758 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_STRIP) 759 { 760 } 761 762 void TriangleStripCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) 763 { 764 outData.resize(5); 765 766 switch (iteration) 767 { 768 case 0: 769 // \note: these values are chosen arbitrarily 770 outData[0] = tcu::Vec4(-0.504f, 0.8f, 0.0f, 1.0f); 771 outData[1] = tcu::Vec4(-0.2f, -0.2f, 0.0f, 1.0f); 772 outData[2] = tcu::Vec4(-0.2f, 0.199f, 0.0f, 1.0f); 773 outData[3] = tcu::Vec4( 0.5f, 0.201f, 0.0f, 1.0f); 774 outData[4] = tcu::Vec4( 1.5f, 0.4f, 0.0f, 1.0f); 775 break; 776 777 case 1: 778 outData[0] = tcu::Vec4(-0.499f, 0.129f, 0.0f, 1.0f); 779 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 780 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 781 outData[3] = tcu::Vec4( 0.11f, -0.31f, 0.0f, 1.0f); 782 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 783 break; 784 785 case 2: 786 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 787 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 788 outData[2] = tcu::Vec4(-0.87f, -0.1f, 0.0f, 1.0f); 789 outData[3] = tcu::Vec4(-0.11f, 0.19f, 0.0f, 1.0f); 790 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 791 break; 792 } 793 794 outTriangles.resize(3); 795 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false; 796 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = true; 797 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = false; 798 799 outTriangles[1].positions[0] = outData[2]; outTriangles[1].sharedEdge[0] = true; 800 outTriangles[1].positions[1] = outData[1]; outTriangles[1].sharedEdge[1] = false; 801 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true; 802 803 outTriangles[2].positions[0] = outData[2]; outTriangles[2].sharedEdge[0] = true; 804 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false; 805 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false; 806 807 // log 808 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage; 809 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 810 { 811 m_testCtx.getLog() 812 << tcu::TestLog::Message 813 << "\t" << outData[vtxNdx] 814 << tcu::TestLog::EndMessage; 815 } 816 } 817 818 class TriangleFanCase : public BaseTriangleCase 819 { 820 public: 821 TriangleFanCase (Context& context, const char* name, const char* desc); 822 823 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles); 824 }; 825 826 TriangleFanCase::TriangleFanCase (Context& context, const char* name, const char* desc) 827 : BaseTriangleCase(context, name, desc, GL_TRIANGLE_FAN) 828 { 829 } 830 831 void TriangleFanCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) 832 { 833 outData.resize(5); 834 835 switch (iteration) 836 { 837 case 0: 838 // \note: these values are chosen arbitrarily 839 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f); 840 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 841 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f); 842 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 843 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f); 844 break; 845 846 case 1: 847 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 848 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 849 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 850 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 851 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 852 break; 853 854 case 2: 855 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 856 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 857 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f); 858 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 859 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 860 break; 861 } 862 863 outTriangles.resize(3); 864 outTriangles[0].positions[0] = outData[0]; outTriangles[0].sharedEdge[0] = false; 865 outTriangles[0].positions[1] = outData[1]; outTriangles[0].sharedEdge[1] = false; 866 outTriangles[0].positions[2] = outData[2]; outTriangles[0].sharedEdge[2] = true; 867 868 outTriangles[1].positions[0] = outData[0]; outTriangles[1].sharedEdge[0] = true; 869 outTriangles[1].positions[1] = outData[2]; outTriangles[1].sharedEdge[1] = false; 870 outTriangles[1].positions[2] = outData[3]; outTriangles[1].sharedEdge[2] = true; 871 872 outTriangles[2].positions[0] = outData[0]; outTriangles[2].sharedEdge[0] = true; 873 outTriangles[2].positions[1] = outData[3]; outTriangles[2].sharedEdge[1] = false; 874 outTriangles[2].positions[2] = outData[4]; outTriangles[2].sharedEdge[2] = false; 875 876 // log 877 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage; 878 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 879 { 880 m_testCtx.getLog() 881 << tcu::TestLog::Message 882 << "\t" << outData[vtxNdx] 883 << tcu::TestLog::EndMessage; 884 } 885 } 886 887 class LinesCase : public BaseLineCase 888 { 889 public: 890 LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness); 891 892 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines); 893 }; 894 895 LinesCase::LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness) 896 : BaseLineCase(context, name, desc, GL_LINES, wideness) 897 { 898 } 899 900 void LinesCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) 901 { 902 outData.resize(6); 903 904 switch (iteration) 905 { 906 case 0: 907 // \note: these values are chosen arbitrarily 908 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f); 909 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 910 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f); 911 outData[3] = tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f); 912 outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f); 913 outData[5] = tcu::Vec4( 0.1f, 0.5f, 0.0f, 1.0f); 914 break; 915 916 case 1: 917 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 918 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 919 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 920 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 921 outData[4] = tcu::Vec4( 0.88f, 0.9f, 0.0f, 1.0f); 922 outData[5] = tcu::Vec4( 0.18f, -0.2f, 0.0f, 1.0f); 923 break; 924 925 case 2: 926 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 927 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 928 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f); 929 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 930 outData[4] = tcu::Vec4( 0.88f, 0.7f, 0.0f, 1.0f); 931 outData[5] = tcu::Vec4( 0.8f, -0.7f, 0.0f, 1.0f); 932 break; 933 } 934 935 outLines.resize(3); 936 outLines[0].positions[0] = outData[0]; 937 outLines[0].positions[1] = outData[1]; 938 outLines[1].positions[0] = outData[2]; 939 outLines[1].positions[1] = outData[3]; 940 outLines[2].positions[0] = outData[4]; 941 outLines[2].positions[1] = outData[5]; 942 943 // log 944 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << m_lineWidth << ")" << tcu::TestLog::EndMessage; 945 for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx) 946 { 947 m_testCtx.getLog() 948 << tcu::TestLog::Message 949 << "Line " << (lineNdx+1) << ":" 950 << "\n\t" << outLines[lineNdx].positions[0] 951 << "\n\t" << outLines[lineNdx].positions[1] 952 << tcu::TestLog::EndMessage; 953 } 954 } 955 956 class LineStripCase : public BaseLineCase 957 { 958 public: 959 LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness); 960 961 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines); 962 }; 963 964 LineStripCase::LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness) 965 : BaseLineCase(context, name, desc, GL_LINE_STRIP, wideness) 966 { 967 } 968 969 void LineStripCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) 970 { 971 outData.resize(4); 972 973 switch (iteration) 974 { 975 case 0: 976 // \note: these values are chosen arbitrarily 977 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f); 978 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 979 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f); 980 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 981 break; 982 983 case 1: 984 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 985 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 986 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 987 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 988 break; 989 990 case 2: 991 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 992 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 993 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f); 994 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 995 break; 996 } 997 998 outLines.resize(3); 999 outLines[0].positions[0] = outData[0]; 1000 outLines[0].positions[1] = outData[1]; 1001 outLines[1].positions[0] = outData[1]; 1002 outLines[1].positions[1] = outData[2]; 1003 outLines[2].positions[0] = outData[2]; 1004 outLines[2].positions[1] = outData[3]; 1005 1006 // log 1007 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage; 1008 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 1009 { 1010 m_testCtx.getLog() 1011 << tcu::TestLog::Message 1012 << "\t" << outData[vtxNdx] 1013 << tcu::TestLog::EndMessage; 1014 } 1015 } 1016 1017 class LineLoopCase : public BaseLineCase 1018 { 1019 public: 1020 LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness); 1021 1022 void generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines); 1023 }; 1024 1025 LineLoopCase::LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness) 1026 : BaseLineCase(context, name, desc, GL_LINE_LOOP, wideness) 1027 { 1028 } 1029 1030 void LineLoopCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) 1031 { 1032 outData.resize(4); 1033 1034 switch (iteration) 1035 { 1036 case 0: 1037 // \note: these values are chosen arbitrarily 1038 outData[0] = tcu::Vec4( 0.01f, 0.0f, 0.0f, 1.0f); 1039 outData[1] = tcu::Vec4( 0.5f, 0.2f, 0.0f, 1.0f); 1040 outData[2] = tcu::Vec4( 0.46f, 0.3f, 0.0f, 1.0f); 1041 outData[3] = tcu::Vec4(-0.5f, 0.2f, 0.0f, 1.0f); 1042 break; 1043 1044 case 1: 1045 outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f); 1046 outData[1] = tcu::Vec4(-0.501f, -0.3f, 0.0f, 1.0f); 1047 outData[2] = tcu::Vec4( 0.11f, -0.2f, 0.0f, 1.0f); 1048 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1049 break; 1050 1051 case 2: 1052 outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f); 1053 outData[1] = tcu::Vec4( 1.1f, -0.9f, 0.0f, 1.0f); 1054 outData[2] = tcu::Vec4( 0.7f, -0.1f, 0.0f, 1.0f); 1055 outData[3] = tcu::Vec4( 0.11f, 0.2f, 0.0f, 1.0f); 1056 break; 1057 } 1058 1059 outLines.resize(4); 1060 outLines[0].positions[0] = outData[0]; 1061 outLines[0].positions[1] = outData[1]; 1062 outLines[1].positions[0] = outData[1]; 1063 outLines[1].positions[1] = outData[2]; 1064 outLines[2].positions[0] = outData[2]; 1065 outLines[2].positions[1] = outData[3]; 1066 outLines[3].positions[0] = outData[3]; 1067 outLines[3].positions[1] = outData[0]; 1068 1069 // log 1070 m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line loop, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage; 1071 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 1072 { 1073 m_testCtx.getLog() 1074 << tcu::TestLog::Message 1075 << "\t" << outData[vtxNdx] 1076 << tcu::TestLog::EndMessage; 1077 } 1078 } 1079 1080 class FillRuleCase : public BaseRenderingCase 1081 { 1082 public: 1083 enum FillRuleCaseType 1084 { 1085 FILLRULECASE_BASIC = 0, 1086 FILLRULECASE_REVERSED, 1087 FILLRULECASE_CLIPPED_FULL, 1088 FILLRULECASE_CLIPPED_PARTIAL, 1089 FILLRULECASE_PROJECTED, 1090 1091 FILLRULECASE_LAST 1092 }; 1093 1094 FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type); 1095 ~FillRuleCase (void); 1096 IterateResult iterate (void); 1097 1098 private: 1099 int getRenderSize (FillRuleCase::FillRuleCaseType type) const; 1100 int getNumIterations (FillRuleCase::FillRuleCaseType type) const; 1101 void generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const; 1102 1103 const FillRuleCaseType m_caseType; 1104 int m_iteration; 1105 const int m_iterationCount; 1106 bool m_allIterationsPassed; 1107 1108 }; 1109 1110 FillRuleCase::FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type) 1111 : BaseRenderingCase (ctx, name, desc, getRenderSize(type)) 1112 , m_caseType (type) 1113 , m_iteration (0) 1114 , m_iterationCount (getNumIterations(type)) 1115 , m_allIterationsPassed (true) 1116 { 1117 DE_ASSERT(type < FILLRULECASE_LAST); 1118 } 1119 1120 FillRuleCase::~FillRuleCase (void) 1121 { 1122 deinit(); 1123 } 1124 1125 FillRuleCase::IterateResult FillRuleCase::iterate (void) 1126 { 1127 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 1128 const tcu::ScopedLogSection section (m_testCtx.getLog(), iterationDescription, iterationDescription); 1129 const int thresholdRed = 1 << (8 - m_context.getRenderTarget().getPixelFormat().redBits); 1130 const int thresholdGreen = 1 << (8 - m_context.getRenderTarget().getPixelFormat().greenBits); 1131 const int thresholdBlue = 1 << (8 - m_context.getRenderTarget().getPixelFormat().blueBits); 1132 tcu::Surface resultImage (m_renderSize, m_renderSize); 1133 std::vector<tcu::Vec4> drawBuffer; 1134 bool imageShown = false; 1135 1136 generateTriangles(m_iteration, drawBuffer); 1137 1138 // draw image 1139 { 1140 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1141 const std::vector<tcu::Vec4> colorBuffer (drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f)); 1142 1143 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage; 1144 1145 gl.enable(GL_BLEND); 1146 gl.blendEquation(GL_FUNC_ADD); 1147 gl.blendFunc(GL_ONE, GL_ONE); 1148 drawPrimitives(resultImage, drawBuffer, colorBuffer, GL_TRIANGLES); 1149 } 1150 1151 // verify no overdraw 1152 { 1153 const tcu::RGBA triangleColor = tcu::RGBA(127, 127, 127, 255); 1154 bool overdraw = false; 1155 1156 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage; 1157 1158 for (int y = 0; y < resultImage.getHeight(); ++y) 1159 for (int x = 0; x < resultImage.getWidth(); ++x) 1160 { 1161 const tcu::RGBA color = resultImage.getPixel(x, y); 1162 1163 // color values are greater than triangle color? Allow lower values for multisampled edges and background. 1164 if ((color.getRed() - triangleColor.getRed()) > thresholdRed || 1165 (color.getGreen() - triangleColor.getGreen()) > thresholdGreen || 1166 (color.getBlue() - triangleColor.getBlue()) > thresholdBlue) 1167 overdraw = true; 1168 } 1169 1170 // results 1171 if (!overdraw) 1172 m_testCtx.getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage; 1173 else 1174 { 1175 m_testCtx.getLog() << tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage; 1176 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering") 1177 << tcu::TestLog::Image("Result", "Result", resultImage) 1178 << tcu::TestLog::EndImageSet; 1179 1180 imageShown = true; 1181 m_allIterationsPassed = false; 1182 } 1183 } 1184 1185 // verify no missing fragments in the full viewport case 1186 if (m_caseType == FILLRULECASE_CLIPPED_FULL) 1187 { 1188 bool missingFragments = false; 1189 1190 m_testCtx.getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage; 1191 1192 for (int y = 0; y < resultImage.getHeight(); ++y) 1193 for (int x = 0; x < resultImage.getWidth(); ++x) 1194 { 1195 const tcu::RGBA color = resultImage.getPixel(x, y); 1196 1197 // black? (background) 1198 if (color.getRed() <= thresholdRed || 1199 color.getGreen() <= thresholdGreen || 1200 color.getBlue() <= thresholdBlue) 1201 missingFragments = true; 1202 } 1203 1204 // results 1205 if (!missingFragments) 1206 m_testCtx.getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage; 1207 else 1208 { 1209 m_testCtx.getLog() << tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage; 1210 1211 if (!imageShown) 1212 { 1213 m_testCtx.getLog() << tcu::TestLog::ImageSet("Result of rendering", "Result of rendering") 1214 << tcu::TestLog::Image("Result", "Result", resultImage) 1215 << tcu::TestLog::EndImageSet; 1216 } 1217 1218 m_allIterationsPassed = false; 1219 } 1220 } 1221 1222 // result 1223 if (++m_iteration == m_iterationCount) 1224 { 1225 if (m_allIterationsPassed) 1226 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1227 else 1228 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixels"); 1229 1230 return STOP; 1231 } 1232 else 1233 return CONTINUE; 1234 } 1235 1236 int FillRuleCase::getRenderSize (FillRuleCase::FillRuleCaseType type) const 1237 { 1238 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL) 1239 return 64; 1240 else 1241 return 256; 1242 } 1243 1244 int FillRuleCase::getNumIterations (FillRuleCase::FillRuleCaseType type) const 1245 { 1246 if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL) 1247 return 15; 1248 else 1249 return 2; 1250 } 1251 1252 void FillRuleCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const 1253 { 1254 switch (m_caseType) 1255 { 1256 case FILLRULECASE_BASIC: 1257 case FILLRULECASE_REVERSED: 1258 case FILLRULECASE_PROJECTED: 1259 { 1260 const int numRows = 4; 1261 const int numColumns = 4; 1262 const float quadSide = 0.15f; 1263 de::Random rnd (0xabcd); 1264 1265 outData.resize(6 * numRows * numColumns); 1266 1267 for (int col = 0; col < numColumns; ++col) 1268 for (int row = 0; row < numRows; ++row) 1269 { 1270 const tcu::Vec2 center = tcu::Vec2(((float)row + 0.5f) / (float)numRows * 2.0f - 1.0f, ((float)col + 0.5f) / (float)numColumns * 2.0f - 1.0f); 1271 const float rotation = float(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f; 1272 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation)); 1273 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x()); 1274 const tcu::Vec2 quad[4] = 1275 { 1276 center + sideH + sideV, 1277 center + sideH - sideV, 1278 center - sideH - sideV, 1279 center - sideH + sideV, 1280 }; 1281 1282 if (m_caseType == FILLRULECASE_BASIC) 1283 { 1284 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1285 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f); 1286 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1287 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1288 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1289 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f); 1290 } 1291 else if (m_caseType == FILLRULECASE_REVERSED) 1292 { 1293 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1294 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f); 1295 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1296 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1297 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1298 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f); 1299 } 1300 else if (m_caseType == FILLRULECASE_PROJECTED) 1301 { 1302 const float w0 = rnd.getFloat(0.1f, 4.0f); 1303 const float w1 = rnd.getFloat(0.1f, 4.0f); 1304 const float w2 = rnd.getFloat(0.1f, 4.0f); 1305 const float w3 = rnd.getFloat(0.1f, 4.0f); 1306 1307 outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0); 1308 outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1); 1309 outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2); 1310 outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2); 1311 outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0); 1312 outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3); 1313 } 1314 else 1315 DE_ASSERT(DE_FALSE); 1316 } 1317 1318 break; 1319 } 1320 1321 case FILLRULECASE_CLIPPED_PARTIAL: 1322 case FILLRULECASE_CLIPPED_FULL: 1323 { 1324 const float quadSide = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f); 1325 const tcu::Vec2 center = (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f)); 1326 const float rotation = (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f; 1327 const tcu::Vec2 sideH = quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation)); 1328 const tcu::Vec2 sideV = tcu::Vec2(sideH.y(), -sideH.x()); 1329 const tcu::Vec2 quad[4] = 1330 { 1331 center + sideH + sideV, 1332 center + sideH - sideV, 1333 center - sideH - sideV, 1334 center - sideH + sideV, 1335 }; 1336 1337 outData.resize(6); 1338 outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1339 outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f); 1340 outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1341 outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f); 1342 outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f); 1343 outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f); 1344 break; 1345 } 1346 1347 default: 1348 DE_ASSERT(DE_FALSE); 1349 } 1350 } 1351 1352 class CullingTest : public BaseRenderingCase 1353 { 1354 public: 1355 CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder); 1356 ~CullingTest (void); 1357 IterateResult iterate (void); 1358 1359 private: 1360 void generateVertices (std::vector<tcu::Vec4>& outData) const; 1361 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const; 1362 bool triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const; 1363 1364 const glw::GLenum m_cullMode; 1365 const glw::GLenum m_primitive; 1366 const glw::GLenum m_faceOrder; 1367 }; 1368 1369 CullingTest::CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder) 1370 : BaseRenderingCase (ctx, name, desc) 1371 , m_cullMode (cullMode) 1372 , m_primitive (primitive) 1373 , m_faceOrder (faceOrder) 1374 { 1375 } 1376 1377 CullingTest::~CullingTest (void) 1378 { 1379 } 1380 1381 CullingTest::IterateResult CullingTest::iterate (void) 1382 { 1383 tcu::Surface resultImage(m_renderSize, m_renderSize); 1384 std::vector<tcu::Vec4> drawBuffer; 1385 std::vector<TriangleSceneSpec::SceneTriangle> triangles; 1386 1387 // generate scene 1388 generateVertices(drawBuffer); 1389 extractTriangles(triangles, drawBuffer); 1390 1391 // draw image 1392 { 1393 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1394 1395 gl.enable(GL_CULL_FACE); 1396 gl.cullFace(m_cullMode); 1397 gl.frontFace(m_faceOrder); 1398 1399 m_testCtx.getLog() << tcu::TestLog::Message << "Setting front face to " << glu::getWindingName(m_faceOrder) << tcu::TestLog::EndMessage; 1400 m_testCtx.getLog() << tcu::TestLog::Message << "Setting cull face to " << glu::getFaceName(m_cullMode) << tcu::TestLog::EndMessage; 1401 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing test pattern (" << glu::getPrimitiveTypeName(m_primitive) << ")" << tcu::TestLog::EndMessage; 1402 1403 drawPrimitives(resultImage, drawBuffer, m_primitive); 1404 } 1405 1406 // compare 1407 { 1408 RasterizationArguments args; 1409 TriangleSceneSpec scene; 1410 1411 args.numSamples = m_numSamples; 1412 args.subpixelBits = m_subpixelBits; 1413 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits; 1414 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits; 1415 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits; 1416 1417 scene.triangles.swap(triangles); 1418 1419 if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), tcu::VERIFICATIONMODE_WEAK)) 1420 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1421 else 1422 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering"); 1423 } 1424 1425 return STOP; 1426 } 1427 1428 void CullingTest::generateVertices (std::vector<tcu::Vec4>& outData) const 1429 { 1430 de::Random rnd(543210); 1431 1432 outData.resize(6); 1433 for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx) 1434 { 1435 outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f); 1436 outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f); 1437 outData[vtxNdx].z() = 0.0f; 1438 outData[vtxNdx].w() = 1.0f; 1439 } 1440 } 1441 1442 void CullingTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const 1443 { 1444 const bool cullDirection = (m_cullMode == GL_FRONT) ^ (m_faceOrder == GL_CCW); 1445 1446 // No triangles 1447 if (m_cullMode == GL_FRONT_AND_BACK) 1448 return; 1449 1450 switch (m_primitive) 1451 { 1452 case GL_TRIANGLES: 1453 { 1454 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3) 1455 { 1456 const tcu::Vec4& v0 = vertices[vtxNdx + 0]; 1457 const tcu::Vec4& v1 = vertices[vtxNdx + 1]; 1458 const tcu::Vec4& v2 = vertices[vtxNdx + 2]; 1459 1460 if (triangleOrder(v0, v1, v2) != cullDirection) 1461 { 1462 TriangleSceneSpec::SceneTriangle tri; 1463 tri.positions[0] = v0; tri.sharedEdge[0] = false; 1464 tri.positions[1] = v1; tri.sharedEdge[1] = false; 1465 tri.positions[2] = v2; tri.sharedEdge[2] = false; 1466 1467 outTriangles.push_back(tri); 1468 } 1469 } 1470 break; 1471 } 1472 1473 case GL_TRIANGLE_STRIP: 1474 { 1475 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx) 1476 { 1477 const tcu::Vec4& v0 = vertices[vtxNdx + 0]; 1478 const tcu::Vec4& v1 = vertices[vtxNdx + 1]; 1479 const tcu::Vec4& v2 = vertices[vtxNdx + 2]; 1480 1481 if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0))) 1482 { 1483 TriangleSceneSpec::SceneTriangle tri; 1484 tri.positions[0] = v0; tri.sharedEdge[0] = false; 1485 tri.positions[1] = v1; tri.sharedEdge[1] = false; 1486 tri.positions[2] = v2; tri.sharedEdge[2] = false; 1487 1488 outTriangles.push_back(tri); 1489 } 1490 } 1491 break; 1492 } 1493 1494 case GL_TRIANGLE_FAN: 1495 { 1496 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) 1497 { 1498 const tcu::Vec4& v0 = vertices[0]; 1499 const tcu::Vec4& v1 = vertices[vtxNdx + 0]; 1500 const tcu::Vec4& v2 = vertices[vtxNdx + 1]; 1501 1502 if (triangleOrder(v0, v1, v2) != cullDirection) 1503 { 1504 TriangleSceneSpec::SceneTriangle tri; 1505 tri.positions[0] = v0; tri.sharedEdge[0] = false; 1506 tri.positions[1] = v1; tri.sharedEdge[1] = false; 1507 tri.positions[2] = v2; tri.sharedEdge[2] = false; 1508 1509 outTriangles.push_back(tri); 1510 } 1511 } 1512 break; 1513 } 1514 1515 default: 1516 DE_ASSERT(false); 1517 } 1518 } 1519 1520 bool CullingTest::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const 1521 { 1522 const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w(); 1523 const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w(); 1524 const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w(); 1525 1526 // cross 1527 return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) < 0; 1528 } 1529 1530 class TriangleInterpolationTest : public BaseRenderingCase 1531 { 1532 public: 1533 TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags); 1534 ~TriangleInterpolationTest (void); 1535 IterateResult iterate (void); 1536 1537 private: 1538 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const; 1539 void extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const; 1540 1541 const glw::GLenum m_primitive; 1542 const bool m_projective; 1543 const int m_iterationCount; 1544 1545 int m_iteration; 1546 bool m_allIterationsPassed; 1547 }; 1548 1549 TriangleInterpolationTest::TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags) 1550 : BaseRenderingCase (ctx, name, desc) 1551 , m_primitive (primitive) 1552 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0) 1553 , m_iterationCount (3) 1554 , m_iteration (0) 1555 , m_allIterationsPassed (true) 1556 { 1557 } 1558 1559 TriangleInterpolationTest::~TriangleInterpolationTest (void) 1560 { 1561 deinit(); 1562 } 1563 1564 TriangleInterpolationTest::IterateResult TriangleInterpolationTest::iterate (void) 1565 { 1566 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 1567 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription); 1568 tcu::Surface resultImage (m_renderSize, m_renderSize); 1569 std::vector<tcu::Vec4> drawBuffer; 1570 std::vector<tcu::Vec4> colorBuffer; 1571 std::vector<TriangleSceneSpec::SceneTriangle> triangles; 1572 1573 // generate scene 1574 generateVertices(m_iteration, drawBuffer, colorBuffer); 1575 extractTriangles(triangles, drawBuffer, colorBuffer); 1576 1577 // log 1578 { 1579 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage; 1580 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx) 1581 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage; 1582 } 1583 1584 // draw image 1585 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive); 1586 1587 // compare 1588 { 1589 RasterizationArguments args; 1590 TriangleSceneSpec scene; 1591 1592 args.numSamples = m_numSamples; 1593 args.subpixelBits = m_subpixelBits; 1594 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits; 1595 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits; 1596 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits; 1597 1598 scene.triangles.swap(triangles); 1599 1600 if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_testCtx.getLog())) 1601 m_allIterationsPassed = false; 1602 } 1603 1604 // result 1605 if (++m_iteration == m_iterationCount) 1606 { 1607 if (m_allIterationsPassed) 1608 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1609 else 1610 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values"); 1611 1612 return STOP; 1613 } 1614 else 1615 return CONTINUE; 1616 } 1617 1618 void TriangleInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const 1619 { 1620 // use only red, green and blue 1621 const tcu::Vec4 colors[] = 1622 { 1623 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), 1624 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), 1625 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), 1626 }; 1627 1628 de::Random rnd(123 + iteration * 1000 + (int)m_primitive); 1629 1630 outVertices.resize(6); 1631 outColors.resize(6); 1632 1633 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx) 1634 { 1635 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f); 1636 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f); 1637 outVertices[vtxNdx].z() = 0.0f; 1638 1639 if (!m_projective) 1640 outVertices[vtxNdx].w() = 1.0f; 1641 else 1642 { 1643 const float w = rnd.getFloat(0.2f, 4.0f); 1644 1645 outVertices[vtxNdx].x() *= w; 1646 outVertices[vtxNdx].y() *= w; 1647 outVertices[vtxNdx].z() *= w; 1648 outVertices[vtxNdx].w() = w; 1649 } 1650 1651 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)]; 1652 } 1653 } 1654 1655 void TriangleInterpolationTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const 1656 { 1657 switch (m_primitive) 1658 { 1659 case GL_TRIANGLES: 1660 { 1661 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3) 1662 { 1663 TriangleSceneSpec::SceneTriangle tri; 1664 tri.positions[0] = vertices[vtxNdx + 0]; 1665 tri.positions[1] = vertices[vtxNdx + 1]; 1666 tri.positions[2] = vertices[vtxNdx + 2]; 1667 tri.sharedEdge[0] = false; 1668 tri.sharedEdge[1] = false; 1669 tri.sharedEdge[2] = false; 1670 1671 tri.colors[0] = colors[vtxNdx + 0]; 1672 tri.colors[1] = colors[vtxNdx + 1]; 1673 tri.colors[2] = colors[vtxNdx + 2]; 1674 1675 outTriangles.push_back(tri); 1676 } 1677 break; 1678 } 1679 1680 case GL_TRIANGLE_STRIP: 1681 { 1682 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx) 1683 { 1684 TriangleSceneSpec::SceneTriangle tri; 1685 tri.positions[0] = vertices[vtxNdx + 0]; 1686 tri.positions[1] = vertices[vtxNdx + 1]; 1687 tri.positions[2] = vertices[vtxNdx + 2]; 1688 tri.sharedEdge[0] = false; 1689 tri.sharedEdge[1] = false; 1690 tri.sharedEdge[2] = false; 1691 1692 tri.colors[0] = colors[vtxNdx + 0]; 1693 tri.colors[1] = colors[vtxNdx + 1]; 1694 tri.colors[2] = colors[vtxNdx + 2]; 1695 1696 outTriangles.push_back(tri); 1697 } 1698 break; 1699 } 1700 1701 case GL_TRIANGLE_FAN: 1702 { 1703 for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) 1704 { 1705 TriangleSceneSpec::SceneTriangle tri; 1706 tri.positions[0] = vertices[0]; 1707 tri.positions[1] = vertices[vtxNdx + 0]; 1708 tri.positions[2] = vertices[vtxNdx + 1]; 1709 tri.sharedEdge[0] = false; 1710 tri.sharedEdge[1] = false; 1711 tri.sharedEdge[2] = false; 1712 1713 tri.colors[0] = colors[0]; 1714 tri.colors[1] = colors[vtxNdx + 0]; 1715 tri.colors[2] = colors[vtxNdx + 1]; 1716 1717 outTriangles.push_back(tri); 1718 } 1719 break; 1720 } 1721 1722 default: 1723 DE_ASSERT(false); 1724 } 1725 } 1726 1727 class LineInterpolationTest : public BaseRenderingCase 1728 { 1729 public: 1730 LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth); 1731 ~LineInterpolationTest (void); 1732 IterateResult iterate (void); 1733 1734 private: 1735 void generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const; 1736 void extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const; 1737 1738 const glw::GLenum m_primitive; 1739 const bool m_projective; 1740 const int m_iterationCount; 1741 1742 int m_iteration; 1743 tcu::ResultCollector m_result; 1744 }; 1745 1746 LineInterpolationTest::LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth) 1747 : BaseRenderingCase (ctx, name, desc) 1748 , m_primitive (primitive) 1749 , m_projective ((flags & INTERPOLATIONFLAGS_PROJECTED) != 0) 1750 , m_iterationCount (3) 1751 , m_iteration (0) 1752 { 1753 m_lineWidth = lineWidth; 1754 } 1755 1756 LineInterpolationTest::~LineInterpolationTest (void) 1757 { 1758 deinit(); 1759 } 1760 1761 LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void) 1762 { 1763 const std::string iterationDescription = "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount); 1764 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription); 1765 tcu::Surface resultImage (m_renderSize, m_renderSize); 1766 std::vector<tcu::Vec4> drawBuffer; 1767 std::vector<tcu::Vec4> colorBuffer; 1768 std::vector<LineSceneSpec::SceneLine> lines; 1769 1770 // generate scene 1771 generateVertices(m_iteration, drawBuffer, colorBuffer); 1772 extractLines(lines, drawBuffer, colorBuffer); 1773 1774 // log 1775 { 1776 m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage; 1777 for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx) 1778 m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage; 1779 } 1780 1781 // draw image 1782 drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive); 1783 1784 // compare 1785 { 1786 RasterizationArguments args; 1787 LineSceneSpec scene; 1788 LineInterpolationMethod iterationResult; 1789 1790 args.numSamples = m_numSamples; 1791 args.subpixelBits = m_subpixelBits; 1792 args.redBits = m_context.getRenderTarget().getPixelFormat().redBits; 1793 args.greenBits = m_context.getRenderTarget().getPixelFormat().greenBits; 1794 args.blueBits = m_context.getRenderTarget().getPixelFormat().blueBits; 1795 1796 scene.lines.swap(lines); 1797 scene.lineWidth = m_lineWidth; 1798 1799 iterationResult = verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog()); 1800 switch (iterationResult) 1801 { 1802 case tcu::LINEINTERPOLATION_STRICTLY_CORRECT: 1803 // line interpolation matches the specification 1804 m_result.addResult(QP_TEST_RESULT_PASS, "Pass"); 1805 break; 1806 1807 case tcu::LINEINTERPOLATION_PROJECTED: 1808 // line interpolation weights are otherwise correct, but they are projected onto major axis 1809 m_testCtx.getLog() << tcu::TestLog::Message 1810 << "Interpolation was calculated using coordinates projected onto major axis. " 1811 "This method does not produce the same values as the non-projecting method defined in the specification." 1812 << tcu::TestLog::EndMessage; 1813 m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Interpolation was calculated using projected coordinateds"); 1814 break; 1815 1816 case tcu::LINEINTERPOLATION_INCORRECT: 1817 if (scene.lineWidth != 1.0f && m_numSamples > 1) 1818 { 1819 // multisampled wide lines might not be supported 1820 m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Interpolation of multisampled wide lines failed"); 1821 } 1822 else 1823 { 1824 // line interpolation is incorrect 1825 m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values"); 1826 } 1827 break; 1828 1829 default: 1830 DE_ASSERT(false); 1831 break; 1832 } 1833 } 1834 1835 // result 1836 if (++m_iteration == m_iterationCount) 1837 { 1838 m_result.setTestContextResult(m_testCtx); 1839 return STOP; 1840 } 1841 else 1842 return CONTINUE; 1843 } 1844 1845 void LineInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const 1846 { 1847 // use only red, green and blue 1848 const tcu::Vec4 colors[] = 1849 { 1850 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f), 1851 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f), 1852 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f), 1853 }; 1854 1855 de::Random rnd(123 + iteration * 1000 + (int)m_primitive); 1856 1857 outVertices.resize(6); 1858 outColors.resize(6); 1859 1860 for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx) 1861 { 1862 outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f); 1863 outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f); 1864 outVertices[vtxNdx].z() = 0.0f; 1865 1866 if (!m_projective) 1867 outVertices[vtxNdx].w() = 1.0f; 1868 else 1869 { 1870 const float w = rnd.getFloat(0.2f, 4.0f); 1871 1872 outVertices[vtxNdx].x() *= w; 1873 outVertices[vtxNdx].y() *= w; 1874 outVertices[vtxNdx].z() *= w; 1875 outVertices[vtxNdx].w() = w; 1876 } 1877 1878 outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)]; 1879 } 1880 } 1881 1882 void LineInterpolationTest::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const 1883 { 1884 switch (m_primitive) 1885 { 1886 case GL_LINES: 1887 { 1888 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2) 1889 { 1890 LineSceneSpec::SceneLine line; 1891 line.positions[0] = vertices[vtxNdx + 0]; 1892 line.positions[1] = vertices[vtxNdx + 1]; 1893 1894 line.colors[0] = colors[vtxNdx + 0]; 1895 line.colors[1] = colors[vtxNdx + 1]; 1896 1897 outLines.push_back(line); 1898 } 1899 break; 1900 } 1901 1902 case GL_LINE_STRIP: 1903 { 1904 for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx) 1905 { 1906 LineSceneSpec::SceneLine line; 1907 line.positions[0] = vertices[vtxNdx + 0]; 1908 line.positions[1] = vertices[vtxNdx + 1]; 1909 1910 line.colors[0] = colors[vtxNdx + 0]; 1911 line.colors[1] = colors[vtxNdx + 1]; 1912 1913 outLines.push_back(line); 1914 } 1915 break; 1916 } 1917 1918 case GL_LINE_LOOP: 1919 { 1920 for (int vtxNdx = 0; vtxNdx < (int)vertices.size(); ++vtxNdx) 1921 { 1922 LineSceneSpec::SceneLine line; 1923 line.positions[0] = vertices[(vtxNdx + 0) % (int)vertices.size()]; 1924 line.positions[1] = vertices[(vtxNdx + 1) % (int)vertices.size()]; 1925 1926 line.colors[0] = colors[(vtxNdx + 0) % (int)vertices.size()]; 1927 line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()]; 1928 1929 outLines.push_back(line); 1930 } 1931 break; 1932 } 1933 1934 default: 1935 DE_ASSERT(false); 1936 } 1937 } 1938 1939 } // anonymous 1940 1941 RasterizationTests::RasterizationTests (Context& context) 1942 : TestCaseGroup(context, "rasterization", "Rasterization Tests") 1943 { 1944 } 1945 1946 RasterizationTests::~RasterizationTests (void) 1947 { 1948 } 1949 1950 void RasterizationTests::init (void) 1951 { 1952 // .primitives 1953 { 1954 tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization"); 1955 1956 addChild(primitives); 1957 1958 primitives->addChild(new TrianglesCase (m_context, "triangles", "Render primitives as GL_TRIANGLES, verify rasterization result")); 1959 primitives->addChild(new TriangleStripCase (m_context, "triangle_strip", "Render primitives as GL_TRIANGLE_STRIP, verify rasterization result")); 1960 primitives->addChild(new TriangleFanCase (m_context, "triangle_fan", "Render primitives as GL_TRIANGLE_FAN, verify rasterization result")); 1961 primitives->addChild(new LinesCase (m_context, "lines", "Render primitives as GL_LINES, verify rasterization result", PRIMITIVEWIDENESS_NARROW)); 1962 primitives->addChild(new LineStripCase (m_context, "line_strip", "Render primitives as GL_LINE_STRIP, verify rasterization result", PRIMITIVEWIDENESS_NARROW)); 1963 primitives->addChild(new LineLoopCase (m_context, "line_loop", "Render primitives as GL_LINE_LOOP, verify rasterization result", PRIMITIVEWIDENESS_NARROW)); 1964 primitives->addChild(new LinesCase (m_context, "lines_wide", "Render primitives as GL_LINES with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE)); 1965 primitives->addChild(new LineStripCase (m_context, "line_strip_wide", "Render primitives as GL_LINE_STRIP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE)); 1966 primitives->addChild(new LineLoopCase (m_context, "line_loop_wide", "Render primitives as GL_LINE_LOOP with wide lines, verify rasterization result", PRIMITIVEWIDENESS_WIDE)); 1967 primitives->addChild(new PointCase (m_context, "points", "Render primitives as GL_POINTS, verify rasterization result", PRIMITIVEWIDENESS_WIDE)); 1968 } 1969 1970 // .limits 1971 { 1972 tcu::TestCaseGroup* const limits = new tcu::TestCaseGroup(m_testCtx, "limits", "Primitive width limits"); 1973 1974 addChild(limits); 1975 1976 limits->addChild(new PointSizeClampedTest(m_context, "points", "gl_PointSize is clamped to ALIASED_POINT_SIZE_RANGE")); 1977 } 1978 1979 // .fill_rules 1980 { 1981 tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules"); 1982 1983 addChild(fillRules); 1984 1985 fillRules->addChild(new FillRuleCase(m_context, "basic_quad", "Verify fill rules", FillRuleCase::FILLRULECASE_BASIC)); 1986 fillRules->addChild(new FillRuleCase(m_context, "basic_quad_reverse", "Verify fill rules", FillRuleCase::FILLRULECASE_REVERSED)); 1987 fillRules->addChild(new FillRuleCase(m_context, "clipped_full", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_FULL)); 1988 fillRules->addChild(new FillRuleCase(m_context, "clipped_partly", "Verify fill rules", FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL)); 1989 fillRules->addChild(new FillRuleCase(m_context, "projected", "Verify fill rules", FillRuleCase::FILLRULECASE_PROJECTED)); 1990 } 1991 1992 // .culling 1993 { 1994 static const struct CullMode 1995 { 1996 glw::GLenum mode; 1997 const char* prefix; 1998 } cullModes[] = 1999 { 2000 { GL_FRONT, "front_" }, 2001 { GL_BACK, "back_" }, 2002 { GL_FRONT_AND_BACK, "both_" }, 2003 }; 2004 static const struct PrimitiveType 2005 { 2006 glw::GLenum type; 2007 const char* name; 2008 } primitiveTypes[] = 2009 { 2010 { GL_TRIANGLES, "triangles" }, 2011 { GL_TRIANGLE_STRIP, "triangle_strip" }, 2012 { GL_TRIANGLE_FAN, "triangle_fan" }, 2013 }; 2014 static const struct FrontFaceOrder 2015 { 2016 glw::GLenum mode; 2017 const char* postfix; 2018 } frontOrders[] = 2019 { 2020 { GL_CCW, "" }, 2021 { GL_CW, "_reverse" }, 2022 }; 2023 2024 tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(m_testCtx, "culling", "Culling"); 2025 2026 addChild(culling); 2027 2028 for (int cullModeNdx = 0; cullModeNdx < DE_LENGTH_OF_ARRAY(cullModes); ++cullModeNdx) 2029 for (int primitiveNdx = 0; primitiveNdx < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx) 2030 for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders); ++frontOrderNdx) 2031 { 2032 const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix; 2033 2034 culling->addChild(new CullingTest(m_context, name.c_str(), "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode)); 2035 } 2036 } 2037 2038 // .interpolation 2039 { 2040 tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Test interpolation"); 2041 2042 addChild(interpolation); 2043 2044 // .basic 2045 { 2046 tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(m_testCtx, "basic", "Non-projective interpolation"); 2047 2048 interpolation->addChild(basic); 2049 2050 basic->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_NONE)); 2051 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_NONE)); 2052 basic->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_NONE)); 2053 basic->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, 1.0f)); 2054 basic->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, 1.0f)); 2055 basic->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, 1.0f)); 2056 basic->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_NONE, 5.0f)); 2057 basic->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_NONE, 5.0f)); 2058 basic->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_NONE, 5.0f)); 2059 } 2060 2061 // .projected 2062 { 2063 tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(m_testCtx, "projected", "Projective interpolation"); 2064 2065 interpolation->addChild(projected); 2066 2067 projected->addChild(new TriangleInterpolationTest (m_context, "triangles", "Verify triangle interpolation", GL_TRIANGLES, INTERPOLATIONFLAGS_PROJECTED)); 2068 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_strip", "Verify triangle strip interpolation", GL_TRIANGLE_STRIP, INTERPOLATIONFLAGS_PROJECTED)); 2069 projected->addChild(new TriangleInterpolationTest (m_context, "triangle_fan", "Verify triangle fan interpolation", GL_TRIANGLE_FAN, INTERPOLATIONFLAGS_PROJECTED)); 2070 projected->addChild(new LineInterpolationTest (m_context, "lines", "Verify line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, 1.0f)); 2071 projected->addChild(new LineInterpolationTest (m_context, "line_strip", "Verify line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, 1.0f)); 2072 projected->addChild(new LineInterpolationTest (m_context, "line_loop", "Verify line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, 1.0f)); 2073 projected->addChild(new LineInterpolationTest (m_context, "lines_wide", "Verify wide line interpolation", GL_LINES, INTERPOLATIONFLAGS_PROJECTED, 5.0f)); 2074 projected->addChild(new LineInterpolationTest (m_context, "line_strip_wide", "Verify wide line strip interpolation", GL_LINE_STRIP, INTERPOLATIONFLAGS_PROJECTED, 5.0f)); 2075 projected->addChild(new LineInterpolationTest (m_context, "line_loop_wide", "Verify wide line loop interpolation", GL_LINE_LOOP, INTERPOLATIONFLAGS_PROJECTED, 5.0f)); 2076 } 2077 } 2078 } 2079 2080 } // Functional 2081 } // gles2 2082 } // deqp 2083