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