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