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