1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Polygon offset tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fPolygonOffsetTests.hpp" 25 #include "deStringUtil.hpp" 26 #include "deRandom.hpp" 27 #include "gluContextInfo.hpp" 28 #include "gluRenderContext.hpp" 29 #include "gluShaderProgram.hpp" 30 #include "gluPixelTransfer.hpp" 31 #include "gluStrUtil.hpp" 32 #include "glwEnums.hpp" 33 #include "glwDefs.hpp" 34 #include "glwFunctions.hpp" 35 #include "tcuTestContext.hpp" 36 #include "tcuTestLog.hpp" 37 #include "tcuTextureUtil.hpp" 38 #include "tcuRenderTarget.hpp" 39 #include "tcuVectorUtil.hpp" 40 #include "rrRenderer.hpp" 41 #include "rrFragmentOperations.hpp" 42 43 #include "sglrReferenceContext.hpp" 44 45 #include <string> 46 #include <limits> 47 48 using namespace glw; // GLint and other GL types 49 50 namespace deqp 51 { 52 namespace gles2 53 { 54 namespace Functional 55 { 56 namespace 57 { 58 59 const char* s_shaderSourceVertex = "attribute highp vec4 a_position;\n" 60 "attribute highp vec4 a_color;\n" 61 "varying mediump vec4 v_color;\n" 62 "void main (void)\n" 63 "{\n" 64 " gl_Position = a_position;\n" 65 " v_color = a_color;\n" 66 "}\n"; 67 const char* s_shaderSourceFragment = "varying mediump vec4 v_color;\n" 68 "void main (void)\n" 69 "{\n" 70 " gl_FragColor = v_color;\n" 71 "}\n"; 72 73 static const tcu::Vec4 MASK_COLOR_OK = tcu::Vec4(0.0f, 0.1f, 0.0f, 1.0f); 74 static const tcu::Vec4 MASK_COLOR_DEV = tcu::Vec4(0.8f, 0.5f, 0.0f, 1.0f); 75 static const tcu::Vec4 MASK_COLOR_FAIL = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f); 76 77 inline bool compareThreshold (const tcu::IVec4& a, const tcu::IVec4& b, const tcu::IVec4& threshold) 78 { 79 return tcu::boolAll(tcu::lessThanEqual(tcu::abs(a - b), threshold)); 80 } 81 82 /*--------------------------------------------------------------------*//*! 83 * \brief Pixelwise comparison of two images. 84 * \note copied & modified from glsRasterizationTests 85 * 86 * Kernel radius defines maximum allowed distance. If radius is 0, only 87 * perfect match is allowed. Radius of 1 gives a 3x3 kernel. 88 * 89 * Return values: -1 = Perfect match 90 * 0 = Deviation within kernel 91 * >0 = Number of faulty pixels 92 *//*--------------------------------------------------------------------*/ 93 int compareImages (tcu::TestLog& log, glu::RenderContext& renderCtx, const tcu::ConstPixelBufferAccess& test, const tcu::ConstPixelBufferAccess& ref, const tcu::PixelBufferAccess& diffMask, int radius) 94 { 95 const int height = test.getHeight(); 96 const int width = test.getWidth(); 97 const int colorThreshold = 128; 98 const tcu::RGBA formatThreshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold(); 99 const tcu::IVec4 threshold = tcu::IVec4(colorThreshold, colorThreshold, colorThreshold, formatThreshold.getAlpha() > 0 ? colorThreshold : 0) 100 + tcu::IVec4(formatThreshold.getRed(), formatThreshold.getGreen(), formatThreshold.getBlue(), formatThreshold.getAlpha()); 101 102 int deviatingPixels = 0; 103 int faultyPixels = 0; 104 int compareFailed = -1; 105 106 tcu::clear(diffMask, MASK_COLOR_OK); 107 108 for (int y = 0; y < height; y++) 109 { 110 for (int x = 0; x < width; x++) 111 { 112 const tcu::IVec4 cRef = ref.getPixelInt(x, y); 113 114 // Pixelwise match, no deviation or fault 115 { 116 const tcu::IVec4 cTest = test.getPixelInt(x, y); 117 if (compareThreshold(cRef, cTest, threshold)) 118 continue; 119 } 120 121 // If not, search within kernel radius 122 { 123 const int kYmin = deMax32(y - radius, 0); 124 const int kYmax = deMin32(y + radius, height-1); 125 const int kXmin = deMax32(x - radius, 0); 126 const int kXmax = deMin32(x + radius, width-1); 127 bool found = false; 128 129 for (int kY = kYmin; kY <= kYmax; kY++) 130 for (int kX = kXmin; kX <= kXmax; kX++) 131 { 132 const tcu::IVec4 cTest = test.getPixelInt(kX, kY); 133 if (compareThreshold(cRef, cTest, threshold)) 134 found = true; 135 } 136 137 if (found) // The pixel is deviating if the color is found inside the kernel 138 { 139 diffMask.setPixel(MASK_COLOR_DEV, x, y); 140 if (compareFailed == -1) 141 compareFailed = 0; 142 deviatingPixels++; 143 continue; 144 } 145 } 146 147 diffMask.setPixel(MASK_COLOR_FAIL, x, y); 148 faultyPixels++; // The pixel is faulty if the color is not found 149 compareFailed = 1; 150 } 151 } 152 153 log << tcu::TestLog::Message << faultyPixels << " faulty pixel(s) found." << tcu::TestLog::EndMessage; 154 155 return (compareFailed == 1 ? faultyPixels : compareFailed); 156 } 157 158 void verifyImages (tcu::TestLog& log, tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const tcu::ConstPixelBufferAccess& testImage, const tcu::ConstPixelBufferAccess& referenceImage) 159 { 160 using tcu::TestLog; 161 162 const int kernelRadius = 1; 163 const int faultyPixelLimit = 20; 164 int faultyPixels; 165 tcu::Surface diffMask (testImage.getWidth(), testImage.getHeight()); 166 167 faultyPixels = compareImages(log, renderCtx, referenceImage, testImage, diffMask.getAccess(), kernelRadius); 168 169 if (faultyPixels > faultyPixelLimit) 170 { 171 log << TestLog::ImageSet("Images", "Image comparison"); 172 log << TestLog::Image("Test image", "Test image", testImage); 173 log << TestLog::Image("Reference image", "Reference image", referenceImage); 174 log << TestLog::Image("Difference mask", "Difference mask", diffMask.getAccess()); 175 log << TestLog::EndImageSet; 176 177 log << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage; 178 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 179 } 180 } 181 182 void verifyError (tcu::TestContext& testCtx, const glw::Functions& gl, GLenum expected) 183 { 184 deUint32 got = gl.getError(); 185 if (got != expected) 186 { 187 testCtx.getLog() << tcu::TestLog::Message << "// ERROR: expected " << glu::getErrorStr(expected) << "; got " << glu::getErrorStr(got) << tcu::TestLog::EndMessage; 188 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) 189 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid error"); 190 } 191 } 192 193 void checkCanvasSize (int width, int height, int minWidth, int minHeight) 194 { 195 if (width < minWidth || height < minHeight) 196 throw tcu::NotSupportedError(std::string("Render context size must be at least ") + de::toString(minWidth) + "x" + de::toString(minWidth)); 197 } 198 199 class PositionColorShader : public sglr::ShaderProgram 200 { 201 public: 202 enum 203 { 204 VARYINGLOC_COLOR = 0 205 }; 206 207 PositionColorShader (void); 208 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 209 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 210 }; 211 212 PositionColorShader::PositionColorShader (void) 213 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 214 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 215 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT) 216 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 217 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 218 << sglr::pdec::VertexSource(s_shaderSourceVertex) 219 << sglr::pdec::FragmentSource(s_shaderSourceFragment)) 220 { 221 } 222 223 void PositionColorShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 224 { 225 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 226 { 227 const int positionAttrLoc = 0; 228 const int colorAttrLoc = 1; 229 230 rr::VertexPacket& packet = *packets[packetNdx]; 231 232 // Transform to position 233 packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx); 234 235 // Pass color to FS 236 packet.outputs[VARYINGLOC_COLOR] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx); 237 } 238 } 239 240 void PositionColorShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 241 { 242 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 243 { 244 rr::FragmentPacket& packet = packets[packetNdx]; 245 246 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 247 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packet, context, VARYINGLOC_COLOR, fragNdx)); 248 } 249 } 250 251 // PolygonOffsetTestCase 252 253 class PolygonOffsetTestCase : public TestCase 254 { 255 public: 256 PolygonOffsetTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName, int canvasSize); 257 258 virtual void testPolygonOffset (void) = DE_NULL; 259 IterateResult iterate (void); 260 261 protected: 262 const GLenum m_internalFormat; 263 const char* m_internalFormatName; 264 const int m_targetSize; 265 }; 266 267 PolygonOffsetTestCase::PolygonOffsetTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName, int canvasSize) 268 : TestCase (context, name, description) 269 , m_internalFormat (internalFormat) 270 , m_internalFormatName (internalFormatName) 271 , m_targetSize (canvasSize) 272 { 273 } 274 275 PolygonOffsetTestCase::IterateResult PolygonOffsetTestCase::iterate (void) 276 { 277 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 278 m_testCtx.getLog() << tcu::TestLog::Message << "Testing PolygonOffset with " << m_internalFormatName << " depth buffer." << tcu::TestLog::EndMessage; 279 280 if (m_internalFormat == 0) 281 { 282 // default framebuffer 283 const int width = m_context.getRenderTarget().getWidth(); 284 const int height = m_context.getRenderTarget().getHeight(); 285 286 checkCanvasSize(width, height, m_targetSize, m_targetSize); 287 288 if (m_context.getRenderTarget().getDepthBits() == 0) 289 throw tcu::NotSupportedError("polygon offset tests require depth buffer"); 290 291 testPolygonOffset(); 292 } 293 else 294 { 295 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 296 297 // framebuffer object 298 GLuint colorRboId = 0; 299 GLuint depthRboId = 0; 300 GLuint fboId = 0; 301 bool fboComplete; 302 303 gl.genRenderbuffers(1, &colorRboId); 304 gl.bindRenderbuffer(GL_RENDERBUFFER, colorRboId); 305 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, m_targetSize, m_targetSize); 306 verifyError(m_testCtx, gl, GL_NO_ERROR); 307 308 gl.genRenderbuffers(1, &depthRboId); 309 gl.bindRenderbuffer(GL_RENDERBUFFER, depthRboId); 310 gl.renderbufferStorage(GL_RENDERBUFFER, m_internalFormat, m_targetSize, m_targetSize); 311 verifyError(m_testCtx, gl, GL_NO_ERROR); 312 313 gl.genFramebuffers(1, &fboId); 314 gl.bindFramebuffer(GL_FRAMEBUFFER, fboId); 315 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRboId); 316 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRboId); 317 verifyError(m_testCtx, gl, GL_NO_ERROR); 318 319 fboComplete = gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE; 320 321 if (fboComplete) 322 testPolygonOffset(); 323 324 gl.deleteFramebuffers(1, &fboId); 325 gl.deleteRenderbuffers(1, &depthRboId); 326 gl.deleteRenderbuffers(1, &colorRboId); 327 328 if (!fboComplete) 329 throw tcu::NotSupportedError("could not create fbo for testing."); 330 } 331 332 return STOP; 333 } 334 335 // UsageTestCase 336 337 class UsageTestCase : public PolygonOffsetTestCase 338 { 339 public: 340 UsageTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName); 341 342 void testPolygonOffset (void); 343 }; 344 345 UsageTestCase::UsageTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName) 346 : PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200) 347 { 348 } 349 350 void UsageTestCase::testPolygonOffset (void) 351 { 352 using tcu::TestLog; 353 354 const tcu::Vec4 triangle[] = 355 { 356 tcu::Vec4(-1, 1, 0, 1), 357 tcu::Vec4( 1, 1, 0, 1), 358 tcu::Vec4( 1, -1, 0, 1), 359 }; 360 361 tcu::TestLog& log = m_testCtx.getLog(); 362 tcu::Surface testImage (m_targetSize, m_targetSize); 363 tcu::Surface referenceImage (m_targetSize, m_targetSize); 364 365 // render test image 366 { 367 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 368 const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment)); 369 const GLint positionLoc = gl.getAttribLocation(program.getProgram(), "a_position"); 370 const GLint colorLoc = gl.getAttribLocation(program.getProgram(), "a_color"); 371 372 if (!program.isOk()) 373 { 374 log << program; 375 TCU_FAIL("Shader compile failed."); 376 } 377 378 gl.clearColor (0, 0, 0, 1); 379 gl.clearDepthf (1.0f); 380 gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 381 gl.viewport (0, 0, m_targetSize, m_targetSize); 382 gl.useProgram (program.getProgram()); 383 gl.enable (GL_DEPTH_TEST); 384 gl.depthFunc (GL_LEQUAL); // make test pass if polygon offset doesn't do anything. It has its own test case. This test is only for to detect always-on cases. 385 386 log << TestLog::Message << "DepthFunc = GL_LEQUAL" << TestLog::EndMessage; 387 388 gl.enableVertexAttribArray (positionLoc); 389 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangle); 390 391 //draw back (offset disabled) 392 393 log << TestLog::Message << "Draw bottom-right. Color = White.\tState: PolygonOffset(0, -2), POLYGON_OFFSET_FILL disabled." << TestLog::EndMessage; 394 395 gl.polygonOffset (0, -2); 396 gl.disable (GL_POLYGON_OFFSET_FILL); 397 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 398 gl.drawArrays (GL_TRIANGLES, 0, 3); 399 400 //draw front 401 402 log << TestLog::Message << "Draw bottom-right. Color = Red.\tState: PolygonOffset(0, -1), POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage; 403 404 gl.polygonOffset (0, -1); 405 gl.enable (GL_POLYGON_OFFSET_FILL); 406 gl.vertexAttrib4f (colorLoc, 1.0f, 0.0f, 0.0f, 1.0f); 407 gl.drawArrays (GL_TRIANGLES, 0, 3); 408 409 gl.disableVertexAttribArray (positionLoc); 410 gl.useProgram (0); 411 gl.finish (); 412 413 glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess()); 414 } 415 416 // render reference image 417 { 418 rr::Renderer referenceRenderer; 419 rr::VertexAttrib attribs[2]; 420 rr::RenderState state((rr::ViewportState)(rr::WindowRectangle(0, 0, m_targetSize, m_targetSize))); 421 422 PositionColorShader program; 423 424 attribs[0].type = rr::VERTEXATTRIBTYPE_FLOAT; 425 attribs[0].size = 4; 426 attribs[0].stride = 0; 427 attribs[0].instanceDivisor = 0; 428 attribs[0].pointer = triangle; 429 430 attribs[1].type = rr::VERTEXATTRIBTYPE_DONT_CARE; 431 attribs[1].generic = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 432 433 tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 434 435 log << TestLog::Message << "Expecting: Bottom-right = Red." << TestLog::EndMessage; 436 437 referenceRenderer.draw( 438 rr::DrawCommand( 439 state, 440 rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(referenceImage.getAccess())), 441 rr::Program(program.getVertexShader(), program.getFragmentShader()), 442 2, 443 attribs, 444 rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0))); 445 } 446 447 // compare 448 verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess()); 449 } 450 451 // UsageDisplacementTestCase 452 453 class UsageDisplacementTestCase : public PolygonOffsetTestCase 454 { 455 public: 456 UsageDisplacementTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName); 457 458 private: 459 tcu::Vec4 genRandomVec4 (de::Random& rnd) const; 460 void testPolygonOffset (void); 461 }; 462 463 UsageDisplacementTestCase::UsageDisplacementTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName) 464 : PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200) 465 { 466 } 467 468 tcu::Vec4 UsageDisplacementTestCase::genRandomVec4 (de::Random& rnd) const 469 { 470 // generater triangle endpoint with following properties 471 // 1) it will not be clipped 472 // 2) it is not near either far or near plane to prevent possible problems related to depth clamping 473 // => w >= 1.0 and z in (-0.9, 0.9) range 474 tcu::Vec4 retVal; 475 476 retVal.x() = rnd.getFloat(-1, 1); 477 retVal.y() = rnd.getFloat(-1, 1); 478 retVal.z() = 0.5f; 479 retVal.w() = 1.0f + rnd.getFloat(); 480 481 return retVal; 482 } 483 484 void UsageDisplacementTestCase::testPolygonOffset (void) 485 { 486 using tcu::TestLog; 487 488 de::Random rnd (0xdec0de); 489 tcu::TestLog& log = m_testCtx.getLog(); 490 tcu::Surface testImage (m_targetSize, m_targetSize); 491 tcu::Surface referenceImage (m_targetSize, m_targetSize); 492 493 // render test image 494 { 495 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 496 const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment)); 497 const GLint positionLoc = gl.getAttribLocation(program.getProgram(), "a_position"); 498 const GLint colorLoc = gl.getAttribLocation(program.getProgram(), "a_color"); 499 const int numIterations = 40; 500 501 if (!program.isOk()) 502 { 503 log << program; 504 TCU_FAIL("Shader compile failed."); 505 } 506 507 gl.clearColor (0, 0, 0, 1); 508 gl.clearDepthf (1.0f); 509 gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 510 gl.viewport (0, 0, m_targetSize, m_targetSize); 511 gl.useProgram (program.getProgram()); 512 gl.enable (GL_DEPTH_TEST); 513 gl.enable (GL_POLYGON_OFFSET_FILL); 514 gl.enableVertexAttribArray (positionLoc); 515 gl.vertexAttrib4f (colorLoc, 0.0f, 1.0f, 0.0f, 1.0f); 516 517 log << TestLog::Message << "Framebuffer cleared, clear color = Black." << TestLog::EndMessage; 518 log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage; 519 520 // draw colorless (mask = 0,0,0) triangle at random* location, set offset and render green triangle with depthfunc = equal 521 // *) w >= 1.0 and z in (-1, 1) range 522 for (int iterationNdx = 0; iterationNdx < numIterations; ++iterationNdx) 523 { 524 const bool offsetDirection = rnd.getBool(); 525 const float offset = offsetDirection ? -1.0f : 1.0f; 526 tcu::Vec4 triangle[3]; 527 528 for (int vertexNdx = 0; vertexNdx < DE_LENGTH_OF_ARRAY(triangle); ++vertexNdx) 529 triangle[vertexNdx] = genRandomVec4(rnd); 530 531 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangle); 532 533 log << TestLog::Message << "Setup triangle with random coordinates:" << TestLog::EndMessage; 534 for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangle); ++ndx) 535 log << TestLog::Message 536 << "\tx=" << triangle[ndx].x() 537 << "\ty=" << triangle[ndx].y() 538 << "\tz=" << triangle[ndx].z() 539 << "\tw=" << triangle[ndx].w() 540 << TestLog::EndMessage; 541 542 log << TestLog::Message << "Draw colorless triangle.\tState: DepthFunc = GL_ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage; 543 544 gl.depthFunc (GL_ALWAYS); 545 gl.polygonOffset (0, 0); 546 gl.colorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 547 gl.drawArrays (GL_TRIANGLES, 0, 3); 548 549 // all fragments should have different Z => DepthFunc == GL_EQUAL fails with every fragment 550 551 log << TestLog::Message << "Draw green triangle.\tState: DepthFunc = GL_EQUAL, PolygonOffset(0, " << offset << ")." << TestLog::EndMessage; 552 553 gl.depthFunc (GL_EQUAL); 554 gl.polygonOffset (0, offset); 555 gl.colorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 556 gl.drawArrays (GL_TRIANGLES, 0, 3); 557 558 log << TestLog::Message << TestLog::EndMessage; // empty line for clarity 559 } 560 561 gl.disableVertexAttribArray (positionLoc); 562 gl.useProgram (0); 563 gl.finish (); 564 565 glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess()); 566 } 567 568 // render reference image 569 log << TestLog::Message << "Expecting black framebuffer." << TestLog::EndMessage; 570 tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 571 572 // compare 573 verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess()); 574 } 575 576 // UsagePositiveNegativeTestCase 577 578 class UsagePositiveNegativeTestCase : public PolygonOffsetTestCase 579 { 580 public: 581 UsagePositiveNegativeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName); 582 583 void testPolygonOffset (void); 584 }; 585 586 UsagePositiveNegativeTestCase::UsagePositiveNegativeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName) 587 : PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200) 588 { 589 } 590 591 void UsagePositiveNegativeTestCase::testPolygonOffset (void) 592 { 593 using tcu::TestLog; 594 595 const tcu::Vec4 triangleBottomRight[] = 596 { 597 tcu::Vec4(-1, 1, 0, 1), 598 tcu::Vec4( 1, 1, 0, 1), 599 tcu::Vec4( 1, -1, 0, 1), 600 }; 601 const tcu::Vec4 triangleTopLeft[] = 602 { 603 tcu::Vec4(-1, -1, 0, 1), 604 tcu::Vec4(-1, 1, 0, 1), 605 tcu::Vec4( 1, -1, 0, 1), 606 }; 607 608 tcu::TestLog& log = m_testCtx.getLog(); 609 tcu::Surface testImage (m_targetSize, m_targetSize); 610 tcu::Surface referenceImage (m_targetSize, m_targetSize); 611 612 // render test image 613 { 614 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 615 const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment)); 616 const GLint positionLoc = gl.getAttribLocation(program.getProgram(), "a_position"); 617 const GLint colorLoc = gl.getAttribLocation(program.getProgram(), "a_color"); 618 619 if (!program.isOk()) 620 { 621 log << program; 622 TCU_FAIL("Shader compile failed."); 623 } 624 625 gl.clearColor (0, 0, 0, 1); 626 gl.clearDepthf (1.0f); 627 gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 628 gl.viewport (0, 0, m_targetSize, m_targetSize); 629 gl.depthFunc (GL_LESS); 630 gl.useProgram (program.getProgram()); 631 gl.enable (GL_DEPTH_TEST); 632 gl.enable (GL_POLYGON_OFFSET_FILL); 633 gl.enableVertexAttribArray (positionLoc); 634 635 log << TestLog::Message << "DepthFunc = GL_LESS." << TestLog::EndMessage; 636 log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage; 637 638 //draw top left (negative offset test) 639 { 640 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleTopLeft); 641 642 log << TestLog::Message << "Draw top-left. Color = White.\tState: PolygonOffset(0, 0)." << TestLog::EndMessage; 643 644 gl.polygonOffset (0, 0); 645 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 646 gl.drawArrays (GL_TRIANGLES, 0, 3); 647 648 log << TestLog::Message << "Draw top-left. Color = Green.\tState: PolygonOffset(0, -1)." << TestLog::EndMessage; 649 650 gl.polygonOffset (0, -1); 651 gl.vertexAttrib4f (colorLoc, 0.0f, 1.0f, 0.0f, 1.0f); 652 gl.drawArrays (GL_TRIANGLES, 0, 3); 653 } 654 655 //draw bottom right (positive offset test) 656 { 657 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleBottomRight); 658 659 log << TestLog::Message << "Draw bottom-right. Color = White.\tState: PolygonOffset(0, 1)." << TestLog::EndMessage; 660 661 gl.polygonOffset (0, 1); 662 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 663 gl.drawArrays (GL_TRIANGLES, 0, 3); 664 665 log << TestLog::Message << "Draw bottom-right. Color = Yellow.\tState: PolygonOffset(0, 0)." << TestLog::EndMessage; 666 667 gl.polygonOffset (0, 0); 668 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 0.0f, 1.0f); 669 gl.drawArrays (GL_TRIANGLES, 0, 3); 670 } 671 672 gl.disableVertexAttribArray (positionLoc); 673 gl.useProgram (0); 674 gl.finish (); 675 676 glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess()); 677 } 678 679 // render reference image 680 { 681 rr::Renderer referenceRenderer; 682 rr::VertexAttrib attribs[2]; 683 rr::RenderState state((rr::ViewportState)(rr::WindowRectangle(0, 0, m_targetSize, m_targetSize))); 684 685 PositionColorShader program; 686 687 attribs[0].type = rr::VERTEXATTRIBTYPE_FLOAT; 688 attribs[0].size = 4; 689 attribs[0].stride = 0; 690 attribs[0].instanceDivisor = 0; 691 attribs[0].pointer = triangleTopLeft; 692 693 attribs[1].type = rr::VERTEXATTRIBTYPE_DONT_CARE; 694 attribs[1].generic = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 695 696 tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 697 698 log << TestLog::Message << "Expecting: Top-left = Green, Bottom-right = Yellow." << TestLog::EndMessage; 699 700 referenceRenderer.draw( 701 rr::DrawCommand( 702 state, 703 rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(referenceImage.getAccess())), 704 rr::Program(program.getVertexShader(), program.getFragmentShader()), 705 2, 706 attribs, 707 rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0))); 708 709 attribs[0].pointer = triangleBottomRight; 710 attribs[1].generic = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f); 711 712 referenceRenderer.draw( 713 rr::DrawCommand( 714 state, 715 rr::RenderTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(referenceImage.getAccess())), 716 rr::Program(program.getVertexShader(), program.getFragmentShader()), 717 2, 718 attribs, 719 rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, 3, 0))); 720 } 721 722 // compare 723 verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess()); 724 } 725 726 // ResultClampingTestCase 727 728 class ResultClampingTestCase : public PolygonOffsetTestCase 729 { 730 public: 731 ResultClampingTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName); 732 733 void testPolygonOffset (void); 734 }; 735 736 ResultClampingTestCase::ResultClampingTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName) 737 : PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200) 738 { 739 } 740 741 void ResultClampingTestCase::testPolygonOffset (void) 742 { 743 using tcu::TestLog; 744 745 const tcu::Vec4 triangleBottomRight[] = 746 { 747 tcu::Vec4(-1, 1, 1, 1), 748 tcu::Vec4( 1, 1, 1, 1), 749 tcu::Vec4( 1, -1, 1, 1), 750 }; 751 const tcu::Vec4 triangleTopLeft[] = 752 { 753 tcu::Vec4(-1, -1, -1, 1), 754 tcu::Vec4(-1, 1, -1, 1), 755 tcu::Vec4( 1, -1, -1, 1), 756 }; 757 758 tcu::TestLog& log = m_testCtx.getLog(); 759 tcu::Surface testImage (m_targetSize, m_targetSize); 760 tcu::Surface referenceImage (m_targetSize, m_targetSize); 761 762 // render test image 763 { 764 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 765 const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment)); 766 const GLint positionLoc = gl.getAttribLocation(program.getProgram(), "a_position"); 767 const GLint colorLoc = gl.getAttribLocation(program.getProgram(), "a_color"); 768 769 if (!program.isOk()) 770 { 771 log << program; 772 TCU_FAIL("Shader compile failed."); 773 } 774 775 gl.clearColor (0, 0, 0, 1); 776 gl.clearDepthf (1.0f); 777 gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 778 gl.viewport (0, 0, m_targetSize, m_targetSize); 779 gl.useProgram (program.getProgram()); 780 gl.enable (GL_DEPTH_TEST); 781 gl.enable (GL_POLYGON_OFFSET_FILL); 782 gl.enableVertexAttribArray (positionLoc); 783 784 log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage; 785 786 //draw bottom right (far) 787 { 788 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleBottomRight); 789 790 log << TestLog::Message << "Draw bottom-right. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 8), Polygon Z = 1.0. (Result depth should clamp to 1.0)." << TestLog::EndMessage; 791 792 gl.depthFunc (GL_ALWAYS); 793 gl.polygonOffset (0, 8); 794 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 795 gl.drawArrays (GL_TRIANGLES, 0, 3); 796 797 log << TestLog::Message << "Draw bottom-right. Color = Red.\tState: DepthFunc = GREATER, PolygonOffset(0, 9), Polygon Z = 1.0. (Result depth should clamp to 1.0 too)" << TestLog::EndMessage; 798 799 gl.depthFunc (GL_GREATER); 800 gl.polygonOffset (0, 9); 801 gl.vertexAttrib4f (colorLoc, 1.0f, 0.0f, 0.0f, 1.0f); 802 gl.drawArrays (GL_TRIANGLES, 0, 3); 803 } 804 805 //draw top left (near) 806 { 807 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleTopLeft); 808 809 log << TestLog::Message << "Draw top-left. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, -8), Polygon Z = -1.0. (Result depth should clamp to -1.0)" << TestLog::EndMessage; 810 811 gl.depthFunc (GL_ALWAYS); 812 gl.polygonOffset (0, -8); 813 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 814 gl.drawArrays (GL_TRIANGLES, 0, 3); 815 816 log << TestLog::Message << "Draw top-left. Color = Yellow.\tState: DepthFunc = LESS, PolygonOffset(0, -9), Polygon Z = -1.0. (Result depth should clamp to -1.0 too)." << TestLog::EndMessage; 817 818 gl.depthFunc (GL_LESS); 819 gl.polygonOffset (0, -9); 820 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 0.0f, 1.0f); 821 gl.drawArrays (GL_TRIANGLES, 0, 3); 822 } 823 824 gl.disableVertexAttribArray (positionLoc); 825 gl.useProgram (0); 826 gl.finish (); 827 828 glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess()); 829 } 830 831 // render reference image 832 log << TestLog::Message << "Expecting: Top-left = White, Bottom-right = White." << TestLog::EndMessage; 833 tcu::clear(referenceImage.getAccess(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); 834 835 // compare 836 verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess()); 837 } 838 839 // UsageSlopeTestCase 840 841 class UsageSlopeTestCase : public PolygonOffsetTestCase 842 { 843 public: 844 UsageSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName); 845 846 void testPolygonOffset (void); 847 }; 848 849 UsageSlopeTestCase::UsageSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName) 850 : PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200) 851 { 852 } 853 854 void UsageSlopeTestCase::testPolygonOffset (void) 855 { 856 using tcu::TestLog; 857 858 const tcu::Vec4 triangleBottomRight[] = 859 { 860 tcu::Vec4(-1, 1, 0.0f, 1), 861 tcu::Vec4( 1, 1, 0.9f, 1), 862 tcu::Vec4( 1, -1, 0.9f, 1), 863 }; 864 const tcu::Vec4 triangleTopLeft[] = 865 { 866 tcu::Vec4(-1, -1, -0.9f, 1), 867 tcu::Vec4(-1, 1, 0.9f, 1), 868 tcu::Vec4( 1, -1, 0.0f, 1), 869 }; 870 871 tcu::TestLog& log = m_testCtx.getLog(); 872 tcu::Surface testImage (m_targetSize, m_targetSize); 873 tcu::Surface referenceImage (m_targetSize, m_targetSize); 874 875 // render test image 876 { 877 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 878 const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment)); 879 const GLint positionLoc = gl.getAttribLocation(program.getProgram(), "a_position"); 880 const GLint colorLoc = gl.getAttribLocation(program.getProgram(), "a_color"); 881 882 if (!program.isOk()) 883 { 884 log << program; 885 TCU_FAIL("Shader compile failed."); 886 } 887 888 gl.clearColor (0, 0, 0, 1); 889 gl.clearDepthf (1.0f); 890 gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 891 gl.viewport (0, 0, m_targetSize, m_targetSize); 892 gl.useProgram (program.getProgram()); 893 gl.enable (GL_DEPTH_TEST); 894 gl.enable (GL_POLYGON_OFFSET_FILL); 895 gl.enableVertexAttribArray (positionLoc); 896 897 log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage; 898 899 //draw top left (negative offset test) 900 { 901 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleTopLeft); 902 903 log << TestLog::Message << "Draw top-left. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage; 904 905 gl.depthFunc (GL_ALWAYS); 906 gl.polygonOffset (0, 0); 907 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 908 gl.drawArrays (GL_TRIANGLES, 0, 3); 909 910 log << TestLog::Message << "Draw top-left. Color = Green.\tState: DepthFunc = LESS, PolygonOffset(-1, 0)." << TestLog::EndMessage; 911 912 gl.depthFunc (GL_LESS); 913 gl.polygonOffset (-1, 0); 914 gl.vertexAttrib4f (colorLoc, 0.0f, 1.0f, 0.0f, 1.0f); 915 gl.drawArrays (GL_TRIANGLES, 0, 3); 916 } 917 918 //draw bottom right (positive offset test) 919 { 920 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangleBottomRight); 921 922 log << TestLog::Message << "Draw bottom-right. Color = White.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage; 923 924 gl.depthFunc (GL_ALWAYS); 925 gl.polygonOffset (0, 0); 926 gl.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 927 gl.drawArrays (GL_TRIANGLES, 0, 3); 928 929 log << TestLog::Message << "Draw bottom-right. Color = Green.\tState: DepthFunc = GREATER, PolygonOffset(1, 0)." << TestLog::EndMessage; 930 931 gl.depthFunc (GL_GREATER); 932 gl.polygonOffset (1, 0); 933 gl.vertexAttrib4f (colorLoc, 0.0f, 1.0f, 0.0f, 1.0f); 934 gl.drawArrays (GL_TRIANGLES, 0, 3); 935 } 936 937 gl.disableVertexAttribArray (positionLoc); 938 gl.useProgram (0); 939 gl.finish (); 940 941 glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess()); 942 } 943 944 // render reference image 945 log << TestLog::Message << "Expecting: Top-left = Green, Bottom-right = Green." << TestLog::EndMessage; 946 tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 947 948 // compare 949 verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess()); 950 } 951 952 // ZeroSlopeTestCase 953 954 class ZeroSlopeTestCase : public PolygonOffsetTestCase 955 { 956 public: 957 ZeroSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName); 958 959 void testPolygonOffset (void); 960 }; 961 962 ZeroSlopeTestCase::ZeroSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName) 963 : PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200) 964 { 965 } 966 967 void ZeroSlopeTestCase::testPolygonOffset (void) 968 { 969 using tcu::TestLog; 970 971 const tcu::Vec4 triangle[] = 972 { 973 tcu::Vec4(-0.4f, 0.4f, 0.0f, 1.0f), 974 tcu::Vec4(-0.8f, -0.5f, 0.0f, 1.0f), 975 tcu::Vec4( 0.7f, 0.2f, 0.0f, 1.0f), 976 }; 977 978 tcu::TestLog& log = m_testCtx.getLog(); 979 tcu::Surface testImage (m_targetSize, m_targetSize); 980 tcu::Surface referenceImage (m_targetSize, m_targetSize); 981 982 // log the triangle 983 log << TestLog::Message << "Setup triangle with coordinates:" << TestLog::EndMessage; 984 for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangle); ++ndx) 985 log << TestLog::Message 986 << "\tx=" << triangle[ndx].x() 987 << "\ty=" << triangle[ndx].y() 988 << "\tz=" << triangle[ndx].z() 989 << "\tw=" << triangle[ndx].w() 990 << TestLog::EndMessage; 991 992 // render test image 993 { 994 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 995 const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment)); 996 const GLint positionLoc = gl.getAttribLocation(program.getProgram(), "a_position"); 997 const GLint colorLoc = gl.getAttribLocation(program.getProgram(), "a_color"); 998 999 if (!program.isOk()) 1000 { 1001 log << program; 1002 TCU_FAIL("Shader compile failed."); 1003 } 1004 1005 gl.clearColor (0, 0, 0, 1); 1006 gl.clearDepthf (1.0f); 1007 gl.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1008 gl.viewport (0, 0, m_targetSize, m_targetSize); 1009 gl.useProgram (program.getProgram()); 1010 gl.enable (GL_DEPTH_TEST); 1011 gl.enable (GL_POLYGON_OFFSET_FILL); 1012 gl.enableVertexAttribArray (positionLoc); 1013 1014 log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage; 1015 1016 { 1017 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangle); 1018 1019 log << TestLog::Message << "Draw triangle. Color = Red.\tState: DepthFunc = ALWAYS, PolygonOffset(0, 0)." << TestLog::EndMessage; 1020 1021 gl.depthFunc (GL_ALWAYS); 1022 gl.polygonOffset (0, 0); 1023 gl.vertexAttrib4f (colorLoc, 1.0f, 0.0f, 0.0f, 1.0f); 1024 gl.drawArrays (GL_TRIANGLES, 0, 3); 1025 1026 log << TestLog::Message << "Draw triangle. Color = Black.\tState: DepthFunc = EQUAL, PolygonOffset(4, 0)." << TestLog::EndMessage; 1027 1028 gl.depthFunc (GL_EQUAL); 1029 gl.polygonOffset (4, 0); // triangle slope == 0 1030 gl.vertexAttrib4f (colorLoc, 0.0f, 0.0f, 0.0f, 1.0f); 1031 gl.drawArrays (GL_TRIANGLES, 0, 3); 1032 } 1033 1034 gl.disableVertexAttribArray (positionLoc); 1035 gl.useProgram (0); 1036 gl.finish (); 1037 1038 glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess()); 1039 } 1040 1041 // render reference image 1042 log << TestLog::Message << "Expecting black triangle." << TestLog::EndMessage; 1043 tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 1044 1045 // compare 1046 verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess()); 1047 } 1048 1049 // OneSlopeTestCase 1050 1051 class OneSlopeTestCase : public PolygonOffsetTestCase 1052 { 1053 public: 1054 OneSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName); 1055 1056 void testPolygonOffset (void); 1057 }; 1058 1059 OneSlopeTestCase::OneSlopeTestCase (Context& context, const char* name, const char* description, GLenum internalFormat, const char* internalFormatName) 1060 : PolygonOffsetTestCase(context, name, description, internalFormat, internalFormatName, 200) 1061 { 1062 } 1063 1064 void OneSlopeTestCase::testPolygonOffset (void) 1065 { 1066 using tcu::TestLog; 1067 1068 /* 1069 * setup vertices subject to following properties 1070 * dz_w / dx_w == 1 1071 * dz_w / dy_w == 0 1072 * or 1073 * dz_w / dx_w == 0 1074 * dz_w / dy_w == 1 1075 * ==> m == 1 1076 */ 1077 const float cornerDepth = float(m_targetSize); 1078 const tcu::Vec4 triangles[2][3] = 1079 { 1080 { 1081 tcu::Vec4(-1, -1, -cornerDepth, 1), 1082 tcu::Vec4(-1, 1, -cornerDepth, 1), 1083 tcu::Vec4( 1, -1, cornerDepth, 1), 1084 }, 1085 { 1086 tcu::Vec4(-1, 1, cornerDepth, 1), 1087 tcu::Vec4( 1, 1, cornerDepth, 1), 1088 tcu::Vec4( 1, -1, -cornerDepth, 1), 1089 }, 1090 }; 1091 1092 tcu::TestLog& log = m_testCtx.getLog(); 1093 tcu::Surface testImage (m_targetSize, m_targetSize); 1094 tcu::Surface referenceImage (m_targetSize, m_targetSize); 1095 1096 // log triangle info 1097 log << TestLog::Message << "Setup triangle0 coordinates: (slope in window coordinates = 1.0)" << TestLog::EndMessage; 1098 for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangles[0]); ++ndx) 1099 log << TestLog::Message 1100 << "\tx=" << triangles[0][ndx].x() 1101 << "\ty=" << triangles[0][ndx].y() 1102 << "\tz=" << triangles[0][ndx].z() 1103 << "\tw=" << triangles[0][ndx].w() 1104 << TestLog::EndMessage; 1105 log << TestLog::Message << "Setup triangle1 coordinates: (slope in window coordinates = 1.0)" << TestLog::EndMessage; 1106 for (size_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(triangles[1]); ++ndx) 1107 log << TestLog::Message 1108 << "\tx=" << triangles[1][ndx].x() 1109 << "\ty=" << triangles[1][ndx].y() 1110 << "\tz=" << triangles[1][ndx].z() 1111 << "\tw=" << triangles[1][ndx].w() 1112 << TestLog::EndMessage; 1113 1114 // render test image 1115 { 1116 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1117 const glu::ShaderProgram program (m_context.getRenderContext(), glu::makeVtxFragSources(s_shaderSourceVertex, s_shaderSourceFragment)); 1118 const GLint positionLoc = gl.getAttribLocation(program.getProgram(), "a_position"); 1119 const GLint colorLoc = gl.getAttribLocation(program.getProgram(), "a_color"); 1120 1121 if (!program.isOk()) 1122 { 1123 log << program; 1124 TCU_FAIL("Shader compile failed."); 1125 } 1126 1127 gl.clearColor (0, 0, 0, 1); 1128 gl.clear (GL_COLOR_BUFFER_BIT); 1129 gl.viewport (0, 0, m_targetSize, m_targetSize); 1130 gl.useProgram (program.getProgram()); 1131 gl.enable (GL_DEPTH_TEST); 1132 gl.enable (GL_POLYGON_OFFSET_FILL); 1133 gl.enableVertexAttribArray (positionLoc); 1134 1135 log << TestLog::Message << "Framebuffer cleared, clear color = Black." << TestLog::EndMessage; 1136 log << TestLog::Message << "POLYGON_OFFSET_FILL enabled." << TestLog::EndMessage; 1137 1138 // top left (positive offset) 1139 { 1140 log << TestLog::Message << "Clear depth to 1.0." << TestLog::EndMessage; 1141 1142 gl.clearDepthf (1.0f); // far 1143 gl.clear (GL_DEPTH_BUFFER_BIT); 1144 1145 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangles[0]); 1146 1147 log << TestLog::Message << "Draw triangle0. Color = Red.\tState: DepthFunc = NOTEQUAL, PolygonOffset(10, 0). (Result depth should clamp to 1.0)." << TestLog::EndMessage; 1148 1149 gl.polygonOffset (10, 0); // clamps any depth on the triangle to 1 1150 gl.depthFunc (GL_NOTEQUAL); 1151 gl.vertexAttrib4f (colorLoc, 1.0f, 0.0f, 0.0f, 1.0f); 1152 gl.drawArrays (GL_TRIANGLES, 0, 3); 1153 } 1154 // bottom right (negative offset) 1155 { 1156 log << TestLog::Message << "Clear depth to 0.0." << TestLog::EndMessage; 1157 1158 gl.clearDepthf (0.0f); // far 1159 gl.clear (GL_DEPTH_BUFFER_BIT); 1160 1161 gl.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, triangles[1]); 1162 1163 log << TestLog::Message << "Draw triangle1. Color = Green.\tState: DepthFunc = NOTEQUAL, PolygonOffset(-10, 0). (Result depth should clamp to 0.0)." << TestLog::EndMessage; 1164 1165 gl.polygonOffset (-10, 0); // clamps depth to 0 1166 gl.depthFunc (GL_NOTEQUAL); 1167 gl.vertexAttrib4f (colorLoc, 0.0f, 1.0f, 0.0f, 1.0f); 1168 gl.drawArrays (GL_TRIANGLES, 0, 3); 1169 } 1170 1171 gl.disableVertexAttribArray (positionLoc); 1172 gl.useProgram (0); 1173 gl.finish (); 1174 1175 glu::readPixels(m_context.getRenderContext(), 0, 0, testImage.getAccess()); 1176 } 1177 1178 // render reference image 1179 log << TestLog::Message << "Expecting black framebuffer." << TestLog::EndMessage; 1180 tcu::clear(referenceImage.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 1181 1182 // compare 1183 verifyImages(log, m_testCtx, m_context.getRenderContext(), testImage.getAccess(), referenceImage.getAccess()); 1184 } 1185 1186 } // anonymous 1187 1188 PolygonOffsetTests::PolygonOffsetTests (Context& context) 1189 : TestCaseGroup(context, "polygon_offset", "Polygon offset tests") 1190 { 1191 } 1192 1193 PolygonOffsetTests::~PolygonOffsetTests (void) 1194 { 1195 } 1196 1197 void PolygonOffsetTests::init (void) 1198 { 1199 const struct DepthBufferFormat 1200 { 1201 enum BufferType 1202 { 1203 TYPE_FIXED_POINT, 1204 TYPE_FLOATING_POINT, 1205 TYPE_UNKNOWN 1206 }; 1207 1208 GLenum internalFormat; 1209 int bits; 1210 BufferType floatingPoint; 1211 const char* name; 1212 } depthFormats[]= 1213 { 1214 { 0, 0, DepthBufferFormat::TYPE_UNKNOWN, "default" }, 1215 { GL_DEPTH_COMPONENT16, 16, DepthBufferFormat::TYPE_FIXED_POINT, "fixed16" }, 1216 }; 1217 1218 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthFormats); ++ndx) 1219 { 1220 const DepthBufferFormat& format = depthFormats[ndx]; 1221 1222 // enable works? 1223 addChild(new UsageTestCase(m_context, (std::string(format.name) + "_enable").c_str(), "test enable GL_POLYGON_OFFSET_FILL", format.internalFormat, format.name)); 1224 1225 // Really moves the polygons ? 1226 addChild(new UsageDisplacementTestCase(m_context, (std::string(format.name) + "_displacement_with_units").c_str(), "test polygon offset", format.internalFormat, format.name)); 1227 1228 // Really moves the polygons to right direction ? 1229 addChild(new UsagePositiveNegativeTestCase(m_context, (std::string(format.name) + "_render_with_units").c_str(), "test polygon offset", format.internalFormat, format.name)); 1230 1231 // Is total result clamped to [0,1] like promised? 1232 addChild(new ResultClampingTestCase(m_context, (std::string(format.name) + "_result_depth_clamp").c_str(), "test polygon offset clamping", format.internalFormat, format.name)); 1233 1234 // Slope really moves the polygon? 1235 addChild(new UsageSlopeTestCase(m_context, (std::string(format.name) + "_render_with_factor").c_str(), "test polygon offset factor", format.internalFormat, format.name)); 1236 1237 // Factor with zero slope 1238 addChild(new ZeroSlopeTestCase(m_context, (std::string(format.name) + "_factor_0_slope").c_str(), "test polygon offset factor", format.internalFormat, format.name)); 1239 1240 // Factor with 1.0 slope 1241 addChild(new OneSlopeTestCase(m_context, (std::string(format.name) + "_factor_1_slope").c_str(), "test polygon offset factor", format.internalFormat, format.name)); 1242 } 1243 } 1244 1245 } // Functional 1246 } // gles2 1247 } // deqp 1248