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