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