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 Clipping tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es2fClippingTests.hpp" 25 #include "tcuRenderTarget.hpp" 26 #include "tcuTextureUtil.hpp" 27 #include "tcuImageCompare.hpp" 28 #include "tcuVectorUtil.hpp" 29 #include "deStringUtil.hpp" 30 #include "deRandom.hpp" 31 32 #include "sglrReferenceContext.hpp" 33 #include "sglrGLContext.hpp" 34 35 #include "glwEnums.hpp" 36 #include "glwDefs.hpp" 37 #include "glwFunctions.hpp" 38 39 using namespace glw; // GLint and other GL types 40 41 namespace deqp 42 { 43 namespace gles2 44 { 45 namespace Functional 46 { 47 namespace 48 { 49 50 using tcu::PixelBufferAccess; 51 using tcu::ConstPixelBufferAccess; 52 using tcu::TestLog; 53 54 static const tcu::Vec4 MASK_COLOR_OK = tcu::Vec4(0.0f, 0.1f, 0.0f, 1.0f); 55 static const tcu::Vec4 MASK_COLOR_DEV = tcu::Vec4(0.8f, 0.5f, 0.0f, 1.0f); 56 static const tcu::Vec4 MASK_COLOR_FAIL = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f); 57 58 const int TEST_CANVAS_SIZE = 200; 59 const rr::WindowRectangle VIEWPORT_WHOLE (0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 60 const rr::WindowRectangle VIEWPORT_CENTER (TEST_CANVAS_SIZE/4, TEST_CANVAS_SIZE/4, TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2); 61 const rr::WindowRectangle VIEWPORT_CORNER (TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2, TEST_CANVAS_SIZE/2); 62 63 64 const char* shaderSourceVertex = "attribute highp vec4 a_position;\n" 65 "attribute highp vec4 a_color;\n" 66 "attribute highp float a_pointSize;\n" 67 "varying mediump vec4 varFragColor;\n" 68 "void main (void)\n" 69 "{\n" 70 " gl_Position = a_position;\n" 71 " gl_PointSize = a_pointSize;\n" 72 " varFragColor = a_color;\n" 73 "}\n"; 74 const char* shaderSourceFragment = "varying mediump vec4 varFragColor;\n" 75 "void main (void)\n" 76 "{\n" 77 " gl_FragColor = varFragColor;\n" 78 "}\n"; 79 80 inline bool isBlack (const tcu::IVec4& a) 81 { 82 return a.x() == 0 && a.y() == 0 && a.z() == 0; 83 } 84 85 inline bool isHalfFilled (const tcu::IVec4& a) 86 { 87 const tcu::IVec4 halfFilled (127, 0, 0, 0); 88 const tcu::IVec4 threshold (20, 256, 256, 256); 89 90 return tcu::boolAll(tcu::lessThanEqual(tcu::abs(a - halfFilled), threshold)); 91 } 92 93 inline bool isLessThanHalfFilled (const tcu::IVec4& a) 94 { 95 const int halfFilled = 127; 96 const int threshold = 20; 97 98 return a.x() + threshold < halfFilled; 99 } 100 101 inline bool compareBlackNonBlackPixels (const tcu::IVec4& a, const tcu::IVec4& b) 102 { 103 return isBlack(a) == isBlack(b); 104 } 105 106 inline bool compareColoredPixels (const tcu::IVec4& a, const tcu::IVec4& b) 107 { 108 const bool aIsBlack = isBlack(a); 109 const bool bIsBlack = isBlack(b); 110 const tcu::IVec4 threshold(20, 20, 20, 0); 111 112 if (aIsBlack && bIsBlack) 113 return true; 114 if (aIsBlack != bIsBlack) 115 return false; 116 117 return tcu::boolAll(tcu::lessThanEqual(tcu::abs(a - b), threshold)); 118 } 119 120 void blitImageOnBlackSurface(const ConstPixelBufferAccess& src, const PixelBufferAccess& dst) 121 { 122 const int height = src.getHeight(); 123 const int width = src.getWidth(); 124 125 for (int y = 0; y < height; y++) 126 for (int x = 0; x < width; x++) 127 { 128 const tcu::IVec4 cSrc = src.getPixelInt(x, y); 129 const tcu::IVec4 cDst = tcu::IVec4(cSrc.x(), cSrc.y(), cSrc.z(), 255); 130 131 dst.setPixel(cDst, x, y); 132 } 133 } 134 135 /*--------------------------------------------------------------------*//*! 136 * \brief Pixelwise comparison of two images. 137 * \note copied & modified from glsRasterizationTests 138 * 139 * Kernel radius defines maximum allowed distance. If radius is 0, only 140 * perfect match is allowed. Radius of 1 gives a 3x3 kernel. Pixels are 141 * equal if pixelCmp returns true.. 142 * 143 * Return values: -1 = Perfect match 144 * 0 = Deviation within kernel 145 * >0 = Number of faulty pixels 146 *//*--------------------------------------------------------------------*/ 147 inline int compareImages (tcu::TestLog& log, const ConstPixelBufferAccess& test, const ConstPixelBufferAccess& ref, const PixelBufferAccess& diffMask, int kernelRadius, bool (*pixelCmp)(const tcu::IVec4& a, const tcu::IVec4& b)) 148 { 149 const int height = test.getHeight(); 150 const int width = test.getWidth(); 151 int deviatingPixels = 0; 152 int faultyPixels = 0; 153 int compareFailed = -1; 154 155 tcu::clear(diffMask, MASK_COLOR_OK); 156 157 for (int y = 0; y < height; y++) 158 { 159 for (int x = 0; x < width; x++) 160 { 161 const tcu::IVec4 cRef = ref.getPixelInt(x, y); 162 const tcu::IVec4 cTest = test.getPixelInt(x, y); 163 164 // Pixelwise match, no deviation or fault 165 if ((*pixelCmp)(cRef, cTest)) 166 continue; 167 168 // Deviation 169 { 170 const int radius = kernelRadius; 171 bool foundRef = false; 172 bool foundTest = false; 173 174 // edges are considered a "deviation" too. The suitable pixel could be "behind" the edge 175 if (y < radius || x < radius || y + radius >= height || x + radius >= width) 176 { 177 foundRef = true; 178 foundTest = true; 179 } 180 else 181 { 182 // find ref 183 for (int kY = y - radius; kY <= y + radius; kY++) 184 for (int kX = x - radius; kX <= x + radius; kX++) 185 { 186 if ((*pixelCmp)(cRef, test.getPixelInt(kX, kY))) 187 { 188 foundRef = true; 189 break; 190 } 191 } 192 193 // find result 194 for (int kY = y - radius; kY <= y + radius; kY++) 195 for (int kX = x - radius; kX <= x + radius; kX++) 196 { 197 if ((*pixelCmp)(cTest, ref.getPixelInt(kX, kY))) 198 { 199 foundTest = true; 200 break; 201 } 202 } 203 } 204 205 // A pixel is deviating if the reference color is found inside the kernel and (~= every pixel reference draws must be drawn by the gl too) 206 // the result color is found in the reference image inside the kernel (~= every pixel gl draws must be drawn by the reference too) 207 if (foundRef && foundTest) 208 { 209 diffMask.setPixel(MASK_COLOR_DEV, x, y); 210 if (compareFailed == -1) 211 compareFailed = 0; 212 deviatingPixels++; 213 continue; 214 } 215 } 216 217 diffMask.setPixel(MASK_COLOR_FAIL, x, y); 218 faultyPixels++; // The pixel is faulty if the color is not found 219 compareFailed = 1; 220 } 221 } 222 223 log << TestLog::Message << deviatingPixels << " deviating pixel(s) found." << TestLog::EndMessage; 224 log << TestLog::Message << faultyPixels << " faulty pixel(s) found." << TestLog::EndMessage; 225 226 return (compareFailed == 1 ? faultyPixels : compareFailed); 227 } 228 229 /*--------------------------------------------------------------------*//*! 230 * \brief Pixelwise comparison of two images. 231 * 232 * Kernel radius defines maximum allowed distance. If radius is 0, only 233 * perfect match is allowed. Radius of 1 gives a 3x3 kernel. Pixels are 234 * equal if they both are black, or both are non-black. 235 * 236 * Return values: -1 = Perfect match 237 * 0 = Deviation within kernel 238 * >0 = Number of faulty pixels 239 *//*--------------------------------------------------------------------*/ 240 int compareBlackNonBlackImages (tcu::TestLog& log, const ConstPixelBufferAccess& test, const ConstPixelBufferAccess& ref, const PixelBufferAccess& diffMask, int kernelRadius) 241 { 242 return compareImages(log, test, ref, diffMask, kernelRadius, compareBlackNonBlackPixels); 243 } 244 245 /*--------------------------------------------------------------------*//*! 246 * \brief Pixelwise comparison of two images. 247 * 248 * Kernel radius defines maximum allowed distance. If radius is 0, only 249 * perfect match is allowed. Radius of 1 gives a 3x3 kernel. Pixels are 250 * equal if they both are black, or both are non-black with color values 251 * close to each other. 252 * 253 * Return values: -1 = Perfect match 254 * 0 = Deviation within kernel 255 * >0 = Number of faulty pixels 256 *//*--------------------------------------------------------------------*/ 257 int compareColoredImages (tcu::TestLog& log, const ConstPixelBufferAccess& test, const ConstPixelBufferAccess& ref, const PixelBufferAccess& diffMask, int kernelRadius) 258 { 259 return compareImages(log, test, ref, diffMask, kernelRadius, compareColoredPixels); 260 } 261 262 /*--------------------------------------------------------------------*//*! 263 * \brief Overdraw check verification 264 * 265 * Check that image does not have at any point a 266 * pixel with red component value > 0.5 267 * 268 * Return values: false = area not filled, or leaking 269 *//*--------------------------------------------------------------------*/ 270 bool checkHalfFilledImageOverdraw (tcu::TestLog& log, const tcu::RenderTarget& m_renderTarget, const ConstPixelBufferAccess& image, const PixelBufferAccess& output) 271 { 272 const int height = image.getHeight(); 273 const int width = image.getWidth(); 274 275 bool faulty = false; 276 277 tcu::clear(output, MASK_COLOR_OK); 278 279 for (int y = 0; y < height; y++) 280 { 281 for (int x = 0; x < width; x++) 282 { 283 const tcu::IVec4 cTest = image.getPixelInt(x, y); 284 285 const bool pixelValid = isBlack(cTest) || isHalfFilled(cTest) || (m_renderTarget.getNumSamples() > 1 && isLessThanHalfFilled(cTest)); 286 287 if (!pixelValid) 288 { 289 output.setPixel(MASK_COLOR_FAIL, x, y); 290 faulty = true; 291 } 292 } 293 } 294 295 if (faulty) 296 log << TestLog::Message << "Faulty pixel(s) found." << TestLog::EndMessage; 297 298 return !faulty; 299 } 300 301 void checkPointSize (const glw::Functions& gl, float pointSize) 302 { 303 GLfloat pointSizeRange[2] = {0,0}; 304 gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, pointSizeRange); 305 if (pointSizeRange[1] < pointSize) 306 throw tcu::NotSupportedError("Maximum point size is too low for this test"); 307 } 308 309 void checkLineWidth (const glw::Functions& gl, float lineWidth) 310 { 311 GLfloat lineWidthRange[2] = {0,0}; 312 gl.getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, lineWidthRange); 313 if (lineWidthRange[1] < lineWidth) 314 throw tcu::NotSupportedError("Maximum line width is too low for this test"); 315 } 316 317 tcu::Vec3 IVec3ToVec3 (const tcu::IVec3& v) 318 { 319 return tcu::Vec3((float)v.x(), (float)v.y(), (float)v.z()); 320 } 321 322 bool pointOnTriangle (const tcu::IVec3& p, const tcu::IVec3& t0, const tcu::IVec3& t1, const tcu::IVec3& t2) 323 { 324 // Must be on the plane 325 const tcu::IVec3 n = tcu::cross(t1 - t0, t2 - t0); 326 const tcu::IVec3 d = (p - t0); 327 328 if (tcu::dot(n, d)) 329 return false; 330 331 // Must be within the triangle area 332 if (deSign32(tcu::dot(n, tcu::cross(t1 - t0, p - t0))) == deSign32(tcu::dot(n, tcu::cross(t2 - t0, p - t0)))) 333 return false; 334 if (deSign32(tcu::dot(n, tcu::cross(t2 - t1, p - t1))) == deSign32(tcu::dot(n, tcu::cross(t0 - t1, p - t1)))) 335 return false; 336 if (deSign32(tcu::dot(n, tcu::cross(t0 - t2, p - t2))) == deSign32(tcu::dot(n, tcu::cross(t1 - t2, p - t2)))) 337 return false; 338 339 return true; 340 } 341 342 bool pointsOnLine (const tcu::IVec2& t0, const tcu::IVec2& t1, const tcu::IVec2& t2) 343 { 344 return (t1 - t0).x() * (t2 - t0).y() - (t2 - t0).x() * (t1 - t0).y() == 0; 345 } 346 347 // returns true for cases where polygon is (almost) along xz or yz planes (normal.z < 0.1) 348 // \note[jarkko] Doesn't have to be accurate, just to detect some obviously bad cases 349 bool twoPointClippedTriangleInvisible(const tcu::Vec3& p, const tcu::IVec3& dir1, const tcu::IVec3& dir2) 350 { 351 // fixed-point-like coords 352 const deInt64 fixedScale = 64; 353 const deInt64 farValue = 1024; 354 const tcu::Vector<deInt64, 3> d1 = tcu::Vector<deInt64, 3>(dir1.x(), dir1.y(), dir1.z()); 355 const tcu::Vector<deInt64, 3> d2 = tcu::Vector<deInt64, 3>(dir2.x(), dir2.y(), dir2.z()); 356 const tcu::Vector<deInt64, 3> pfixed = tcu::Vector<deInt64, 3>(deFloorFloatToInt32(p.x() * fixedScale), deFloorFloatToInt32(p.y() * fixedScale), deFloorFloatToInt32(p.z() * fixedScale)); 357 const tcu::Vector<deInt64, 3> normalDir = tcu::cross(d1*farValue - pfixed, d2*farValue - pfixed); 358 const deInt64 normalLen2 = tcu::lengthSquared(normalDir); 359 360 return (normalDir.z() * normalDir.z() - normalLen2/100) < 0; 361 } 362 363 std::string genClippingPointInfoString(const tcu::Vec4& p) 364 { 365 std::ostringstream msg; 366 367 if (p.x() < -p.w()) msg << "\t(-X clip)"; 368 if (p.x() > p.w()) msg << "\t(+X clip)"; 369 if (p.y() < -p.w()) msg << "\t(-Y clip)"; 370 if (p.y() > p.w()) msg << "\t(+Y clip)"; 371 if (p.z() < -p.w()) msg << "\t(-Z clip)"; 372 if (p.z() > p.w()) msg << "\t(+Z clip)"; 373 374 return msg.str(); 375 } 376 377 std::string genColorString(const tcu::Vec4& p) 378 { 379 const tcu::Vec4 white (1.0f, 1.0f, 1.0f, 1.0f); 380 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); 381 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f); 382 const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f); 383 384 if (p == white) return "(white)"; 385 if (p == red) return "(red)"; 386 if (p == yellow) return "(yellow)"; 387 if (p == blue) return "(blue)"; 388 return ""; 389 } 390 391 class PositionColorShader : public sglr::ShaderProgram 392 { 393 public: 394 enum 395 { 396 VARYINGLOC_COLOR = 0 397 }; 398 399 PositionColorShader (void); 400 401 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const; 402 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const; 403 }; 404 405 PositionColorShader::PositionColorShader (void) 406 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration() 407 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT) 408 << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT) 409 << sglr::pdec::VertexAttribute("a_pointSize", rr::GENERICVECTYPE_FLOAT) 410 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT) 411 << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT) 412 << sglr::pdec::VertexSource(shaderSourceVertex) 413 << sglr::pdec::FragmentSource(shaderSourceFragment)) 414 { 415 } 416 417 void PositionColorShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 418 { 419 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 420 { 421 const int positionAttrLoc = 0; 422 const int colorAttrLoc = 1; 423 const int pointSizeAttrLoc = 2; 424 425 rr::VertexPacket& packet = *packets[packetNdx]; 426 427 // Transform to position 428 packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx); 429 430 // output point size 431 packet.pointSize = rr::readVertexAttribFloat(inputs[pointSizeAttrLoc], packet.instanceNdx, packet.vertexNdx).x(); 432 433 // Pass color to FS 434 packet.outputs[VARYINGLOC_COLOR] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx); 435 } 436 } 437 438 void PositionColorShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 439 { 440 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 441 { 442 rr::FragmentPacket& packet = packets[packetNdx]; 443 444 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 445 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, VARYINGLOC_COLOR, fragNdx)); 446 } 447 } 448 449 class RenderTestCase : public TestCase 450 { 451 public: 452 RenderTestCase (Context& context, const char* name, const char* description); 453 454 virtual void testRender (void) = DE_NULL; 455 virtual void init (void) { } 456 457 IterateResult iterate (void); 458 }; 459 460 RenderTestCase::RenderTestCase (Context& context, const char* name, const char* description) 461 : TestCase (context, name, description) 462 { 463 } 464 465 RenderTestCase::IterateResult RenderTestCase::iterate (void) 466 { 467 const int width = m_context.getRenderTarget().getWidth(); 468 const int height = m_context.getRenderTarget().getHeight(); 469 470 m_testCtx.getLog() << TestLog::Message << "Render target size: " << width << "x" << height << TestLog::EndMessage; 471 if (width < TEST_CANVAS_SIZE || height < TEST_CANVAS_SIZE) 472 throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(TEST_CANVAS_SIZE) + "x" + de::toString(TEST_CANVAS_SIZE)); 473 474 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); // success by default 475 testRender(); 476 477 return STOP; 478 } 479 480 class PointCase : public RenderTestCase 481 { 482 public: 483 PointCase (Context& context, const char* name, const char* description, const tcu::Vec4* pointsBegin, const tcu::Vec4* pointsEnd, float pointSize, const rr::WindowRectangle& viewport); 484 485 void init (void); 486 void testRender (void); 487 488 private: 489 const std::vector<tcu::Vec4> m_points; 490 const float m_pointSize; 491 const rr::WindowRectangle m_viewport; 492 }; 493 494 PointCase::PointCase (Context& context, const char* name, const char* description, const tcu::Vec4* pointsBegin, const tcu::Vec4* pointsEnd, float pointSize, const rr::WindowRectangle& viewport) 495 : RenderTestCase(context, name, description) 496 , m_points (pointsBegin, pointsEnd) 497 , m_pointSize (pointSize) 498 , m_viewport (viewport) 499 { 500 } 501 502 void PointCase::init (void) 503 { 504 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 505 checkPointSize (gl, m_pointSize); 506 } 507 508 void PointCase::testRender (void) 509 { 510 using tcu::TestLog; 511 512 const int numSamples = de::max(m_context.getRenderTarget().getNumSamples(), 1); 513 514 tcu::TestLog& log = m_testCtx.getLog(); 515 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE)); 516 sglr::ReferenceContextLimits limits; 517 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples); 518 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); 519 PositionColorShader program; 520 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 521 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 522 sglr::Context* contexts[2] = {&glesContext, &refContext}; 523 tcu::Surface* surfaces[2] = {&testSurface, &refSurface}; 524 525 // log the purpose of the test 526 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage; 527 log << TestLog::Message << "Rendering points with point size " << m_pointSize << ". Coordinates:" << TestLog::EndMessage; 528 for (size_t ndx = 0; ndx < m_points.size(); ++ndx) 529 log << TestLog::Message 530 << "\tx=" << m_points[ndx].x() 531 << "\ty=" << m_points[ndx].y() 532 << "\tz=" << m_points[ndx].z() 533 << "\tw=" << m_points[ndx].w() 534 << "\t" << genClippingPointInfoString(m_points[ndx]) 535 << TestLog::EndMessage; 536 537 for (int contextNdx = 0; contextNdx < 2; ++contextNdx) 538 { 539 sglr::Context& ctx = *contexts[contextNdx]; 540 tcu::Surface& dstSurface = *surfaces[contextNdx]; 541 const deUint32 programId = ctx.createProgram(&program); 542 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position"); 543 const GLint pointSizeLoc = ctx.getAttribLocation(programId, "a_pointSize"); 544 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color"); 545 546 ctx.clearColor (0, 0, 0, 1); 547 ctx.clearDepthf (1.0f); 548 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 549 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height); 550 ctx.useProgram (programId); 551 ctx.enableVertexAttribArray (positionLoc); 552 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &m_points[0]); 553 ctx.vertexAttrib1f (pointSizeLoc, m_pointSize); 554 ctx.vertexAttrib4f (colorLoc, 1.0f, 1.0f, 1.0f, 1.0f); 555 ctx.drawArrays (GL_POINTS, 0, (glw::GLsizei)m_points.size()); 556 ctx.disableVertexAttribArray (positionLoc); 557 ctx.useProgram (0); 558 ctx.deleteProgram (programId); 559 ctx.finish (); 560 561 ctx.readPixels(dstSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 562 } 563 564 // do the comparison 565 { 566 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 567 const int kernelRadius = 1; 568 int faultyPixels; 569 570 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage; 571 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage; 572 573 faultyPixels = compareBlackNonBlackImages(log, testSurface.getAccess(), refSurface.getAccess(), diffMask.getAccess(), kernelRadius); 574 575 if (faultyPixels > 0) 576 { 577 log << TestLog::ImageSet("Images", "Image comparison") 578 << TestLog::Image("TestImage", "Test image", testSurface.getAccess()) 579 << TestLog::Image("ReferenceImage", "Reference image", refSurface.getAccess()) 580 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess()) 581 << TestLog::EndImageSet 582 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage; 583 584 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 585 } 586 } 587 } 588 589 class LineRenderTestCase : public RenderTestCase 590 { 591 public: 592 struct ColoredLineData 593 { 594 tcu::Vec4 p0; 595 tcu::Vec4 c0; 596 tcu::Vec4 p1; 597 tcu::Vec4 c1; 598 }; 599 600 struct ColorlessLineData 601 { 602 tcu::Vec4 p0; 603 tcu::Vec4 p1; 604 }; 605 LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport); 606 LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport); 607 608 virtual void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) = DE_NULL; 609 void init (void); 610 void testRender (void); 611 612 protected: 613 const float m_lineWidth; 614 615 private: 616 std::vector<ColoredLineData> convertToColoredLines (const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd); 617 618 const std::vector<ColoredLineData> m_lines; 619 const rr::WindowRectangle m_viewport; 620 }; 621 622 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColoredLineData* linesBegin, const ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport) 623 : RenderTestCase (context, name, description) 624 , m_lineWidth (lineWidth) 625 , m_lines (linesBegin, linesEnd) 626 , m_viewport (viewport) 627 { 628 } 629 630 LineRenderTestCase::LineRenderTestCase (Context& context, const char* name, const char* description, const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport) 631 : RenderTestCase (context, name, description) 632 , m_lineWidth (lineWidth) 633 , m_lines (convertToColoredLines(linesBegin, linesEnd)) 634 , m_viewport (viewport) 635 { 636 } 637 638 void LineRenderTestCase::init (void) 639 { 640 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 641 checkLineWidth (gl, m_lineWidth); 642 } 643 644 void LineRenderTestCase::testRender (void) 645 { 646 using tcu::TestLog; 647 648 const int numSamples = de::max(m_context.getRenderTarget().getNumSamples(), 1); 649 const int verticesPerLine = 2; 650 651 tcu::TestLog& log = m_testCtx.getLog(); 652 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE)); 653 sglr::ReferenceContextLimits limits; 654 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples); 655 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); 656 PositionColorShader program; 657 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 658 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 659 sglr::Context* contexts[2] = {&glesContext, &refContext}; 660 tcu::Surface* surfaces[2] = {&testSurface, &refSurface}; 661 662 // log the purpose of the test 663 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage; 664 log << TestLog::Message << "Rendering lines with line width " << m_lineWidth << ". Coordinates:" << TestLog::EndMessage; 665 for (size_t ndx = 0; ndx < m_lines.size(); ++ndx) 666 { 667 const std::string fromProperties = genClippingPointInfoString(m_lines[ndx].p0); 668 const std::string toProperties = genClippingPointInfoString(m_lines[ndx].p1); 669 670 log << TestLog::Message << "\tfrom (x=" << m_lines[ndx].p0.x() << "\ty=" << m_lines[ndx].p0.y() << "\tz=" << m_lines[ndx].p0.z() << "\tw=" << m_lines[ndx].p0.w() << ")\t" << fromProperties << TestLog::EndMessage; 671 log << TestLog::Message << "\tto (x=" << m_lines[ndx].p1.x() << "\ty=" << m_lines[ndx].p1.y() << "\tz=" << m_lines[ndx].p1.z() << "\tw=" << m_lines[ndx].p1.w() << ")\t" << toProperties << TestLog::EndMessage; 672 log << TestLog::Message << TestLog::EndMessage; 673 } 674 675 // render test image 676 for (int contextNdx = 0; contextNdx < 2; ++contextNdx) 677 { 678 sglr::Context& ctx = *contexts[contextNdx]; 679 tcu::Surface& dstSurface = *surfaces[contextNdx]; 680 const deUint32 programId = ctx.createProgram(&program); 681 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position"); 682 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color"); 683 684 ctx.clearColor (0, 0, 0, 1); 685 ctx.clearDepthf (1.0f); 686 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 687 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height); 688 ctx.useProgram (programId); 689 ctx.enableVertexAttribArray (positionLoc); 690 ctx.enableVertexAttribArray (colorLoc); 691 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_lines[0].p0); 692 ctx.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_lines[0].c0); 693 ctx.lineWidth (m_lineWidth); 694 ctx.drawArrays (GL_LINES, 0, verticesPerLine * (glw::GLsizei)m_lines.size()); 695 ctx.disableVertexAttribArray (positionLoc); 696 ctx.disableVertexAttribArray (colorLoc); 697 ctx.useProgram (0); 698 ctx.deleteProgram (programId); 699 ctx.finish (); 700 701 ctx.readPixels(dstSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 702 } 703 704 // compare 705 verifyImage(testSurface.getAccess(), refSurface.getAccess()); 706 } 707 708 std::vector<LineRenderTestCase::ColoredLineData> LineRenderTestCase::convertToColoredLines(const ColorlessLineData* linesBegin, const ColorlessLineData* linesEnd) 709 { 710 std::vector<ColoredLineData> ret; 711 712 for (const ColorlessLineData* it = linesBegin; it != linesEnd; ++it) 713 { 714 ColoredLineData r; 715 716 r.p0 = (*it).p0; 717 r.c0 = tcu::Vec4(1, 1, 1, 1); 718 r.p1 = (*it).p1; 719 r.c1 = tcu::Vec4(1, 1, 1, 1); 720 721 ret.push_back(r); 722 } 723 724 return ret; 725 } 726 727 class LineCase : public LineRenderTestCase 728 { 729 public: 730 LineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColorlessLineData* linesBegin, const LineRenderTestCase::ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport, int searchKernelSize = 1); 731 732 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess); 733 734 private: 735 const int m_searchKernelSize; 736 }; 737 738 LineCase::LineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColorlessLineData* linesBegin, const LineRenderTestCase::ColorlessLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport, int searchKernelSize) 739 : LineRenderTestCase (context, name, description, linesBegin, linesEnd, lineWidth, viewport) 740 , m_searchKernelSize (searchKernelSize) 741 { 742 } 743 744 void LineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) 745 { 746 const int faultyLimit = 6; 747 int faultyPixels; 748 749 const bool isMsaa = m_context.getRenderTarget().getNumSamples() > 1; 750 tcu::TestLog& log = m_testCtx.getLog(); 751 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 752 753 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage; 754 log << TestLog::Message << "Deviation within radius of " << m_searchKernelSize << " is allowed." << TestLog::EndMessage; 755 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage; 756 757 faultyPixels = compareBlackNonBlackImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), m_searchKernelSize); 758 759 if (faultyPixels > faultyLimit) 760 { 761 log << TestLog::ImageSet("Images", "Image comparison") 762 << TestLog::Image("TestImage", "Test image", testImageAccess) 763 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess) 764 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess()) 765 << TestLog::EndImageSet 766 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage; 767 768 if (m_lineWidth != 1.0f && isMsaa) 769 { 770 log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage; 771 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed"); 772 } 773 else 774 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 775 } 776 } 777 778 class ColoredLineCase : public LineRenderTestCase 779 { 780 public: 781 ColoredLineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColoredLineData* linesBegin, const LineRenderTestCase::ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport); 782 783 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess); 784 }; 785 786 ColoredLineCase::ColoredLineCase (Context& context, const char* name, const char* description, const LineRenderTestCase::ColoredLineData* linesBegin, const LineRenderTestCase::ColoredLineData* linesEnd, float lineWidth, const rr::WindowRectangle& viewport) 787 : LineRenderTestCase (context, name, description, linesBegin, linesEnd, lineWidth, viewport) 788 { 789 } 790 791 void ColoredLineCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) 792 { 793 const bool msaa = m_context.getRenderTarget().getNumSamples() > 1; 794 tcu::TestLog& log = m_testCtx.getLog(); 795 796 if (!msaa) 797 { 798 const int kernelRadius = 1; 799 const int faultyLimit = 6; 800 int faultyPixels; 801 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 802 803 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage; 804 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage; 805 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage; 806 807 faultyPixels = compareColoredImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), kernelRadius); 808 809 if (faultyPixels > faultyLimit) 810 { 811 log << TestLog::ImageSet("Images", "Image comparison") 812 << TestLog::Image("TestImage", "Test image", testImageAccess) 813 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess) 814 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess()) 815 << TestLog::EndImageSet 816 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage; 817 818 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 819 } 820 } 821 else 822 { 823 const float threshold = 0.3f; 824 if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR)) 825 { 826 if (m_lineWidth != 1.0f) 827 { 828 log << TestLog::Message << "Wide line support is optional, reporting compatibility warning." << TestLog::EndMessage; 829 m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Wide line clipping failed"); 830 } 831 else 832 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 833 } 834 } 835 } 836 837 class TriangleCaseBase : public RenderTestCase 838 { 839 public: 840 struct TriangleData 841 { 842 tcu::Vec4 p0; 843 tcu::Vec4 c0; 844 tcu::Vec4 p1; 845 tcu::Vec4 c1; 846 tcu::Vec4 p2; 847 tcu::Vec4 c2; 848 }; 849 850 TriangleCaseBase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport); 851 852 virtual void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) = DE_NULL; 853 void testRender (void); 854 855 private: 856 const std::vector<TriangleData> m_polys; 857 const rr::WindowRectangle m_viewport; 858 }; 859 860 TriangleCaseBase::TriangleCaseBase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport) 861 : RenderTestCase(context, name, description) 862 , m_polys (polysBegin, polysEnd) 863 , m_viewport (viewport) 864 { 865 } 866 867 void TriangleCaseBase::testRender (void) 868 { 869 using tcu::TestLog; 870 871 const int numSamples = de::max(m_context.getRenderTarget().getNumSamples(), 1); 872 const int verticesPerTriangle = 3; 873 874 tcu::TestLog& log = m_testCtx.getLog(); 875 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE)); 876 sglr::ReferenceContextLimits limits; 877 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples); 878 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); 879 PositionColorShader program; 880 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 881 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 882 sglr::Context* contexts[2] = {&glesContext, &refContext}; 883 tcu::Surface* surfaces[2] = {&testSurface, &refSurface}; 884 885 // log the purpose of the test 886 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage; 887 log << TestLog::Message << "Rendering triangles. Coordinates:" << TestLog::EndMessage; 888 for (size_t ndx = 0; ndx < m_polys.size(); ++ndx) 889 { 890 const std::string v0Properties = genClippingPointInfoString(m_polys[ndx].p0); 891 const std::string v1Properties = genClippingPointInfoString(m_polys[ndx].p1); 892 const std::string v2Properties = genClippingPointInfoString(m_polys[ndx].p2); 893 const std::string c0Properties = genColorString(m_polys[ndx].c0); 894 const std::string c1Properties = genColorString(m_polys[ndx].c1); 895 const std::string c2Properties = genColorString(m_polys[ndx].c2); 896 897 log << TestLog::Message << "\tv0 (x=" << m_polys[ndx].p0.x() << "\ty=" << m_polys[ndx].p0.y() << "\tz=" << m_polys[ndx].p0.z() << "\tw=" << m_polys[ndx].p0.w() << ")\t" << v0Properties << "\t" << c0Properties << TestLog::EndMessage; 898 log << TestLog::Message << "\tv1 (x=" << m_polys[ndx].p1.x() << "\ty=" << m_polys[ndx].p1.y() << "\tz=" << m_polys[ndx].p1.z() << "\tw=" << m_polys[ndx].p1.w() << ")\t" << v1Properties << "\t" << c1Properties << TestLog::EndMessage; 899 log << TestLog::Message << "\tv2 (x=" << m_polys[ndx].p2.x() << "\ty=" << m_polys[ndx].p2.y() << "\tz=" << m_polys[ndx].p2.z() << "\tw=" << m_polys[ndx].p2.w() << ")\t" << v2Properties << "\t" << c2Properties << TestLog::EndMessage; 900 log << TestLog::Message << TestLog::EndMessage; 901 } 902 903 // render test image 904 for (int contextNdx = 0; contextNdx < 2; ++contextNdx) 905 { 906 sglr::Context& ctx = *contexts[contextNdx]; 907 tcu::Surface& dstSurface = *surfaces[contextNdx]; 908 const deUint32 programId = ctx.createProgram(&program); 909 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position"); 910 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color"); 911 912 ctx.clearColor (0, 0, 0, 1); 913 ctx.clearDepthf (1.0f); 914 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 915 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height); 916 ctx.useProgram (programId); 917 ctx.enableVertexAttribArray (positionLoc); 918 ctx.enableVertexAttribArray (colorLoc); 919 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_polys[0].p0); 920 ctx.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_polys[0].c0); 921 ctx.drawArrays (GL_TRIANGLES, 0, verticesPerTriangle * (glw::GLsizei)m_polys.size()); 922 ctx.disableVertexAttribArray (positionLoc); 923 ctx.disableVertexAttribArray (colorLoc); 924 ctx.useProgram (0); 925 ctx.deleteProgram (programId); 926 ctx.finish (); 927 928 ctx.readPixels(dstSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 929 } 930 931 verifyImage(testSurface.getAccess(), refSurface.getAccess()); 932 } 933 934 class TriangleCase : public TriangleCaseBase 935 { 936 public: 937 TriangleCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport); 938 939 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess); 940 }; 941 942 TriangleCase::TriangleCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport) 943 : TriangleCaseBase(context, name, description, polysBegin, polysEnd, viewport) 944 { 945 } 946 947 void TriangleCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) 948 { 949 const int kernelRadius = 1; 950 const int faultyLimit = 6; 951 tcu::TestLog& log = m_testCtx.getLog(); 952 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 953 int faultyPixels; 954 955 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage; 956 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage; 957 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage; 958 959 faultyPixels = compareBlackNonBlackImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), kernelRadius); 960 961 if (faultyPixels > faultyLimit) 962 { 963 log << TestLog::ImageSet("Images", "Image comparison") 964 << TestLog::Image("TestImage", "Test image", testImageAccess) 965 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess) 966 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess()) 967 << TestLog::EndImageSet 968 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage; 969 970 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 971 } 972 } 973 974 class TriangleAttributeCase : public TriangleCaseBase 975 { 976 public: 977 TriangleAttributeCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport); 978 979 void verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess); 980 }; 981 982 TriangleAttributeCase::TriangleAttributeCase (Context& context, const char* name, const char* description, const TriangleData* polysBegin, const TriangleData* polysEnd, const rr::WindowRectangle& viewport) 983 : TriangleCaseBase(context, name, description, polysBegin, polysEnd, viewport) 984 { 985 } 986 987 void TriangleAttributeCase::verifyImage (const tcu::ConstPixelBufferAccess& testImageAccess, const tcu::ConstPixelBufferAccess& referenceImageAccess) 988 { 989 const bool msaa = m_context.getRenderTarget().getNumSamples() > 1; 990 tcu::TestLog& log = m_testCtx.getLog(); 991 992 if (!msaa) 993 { 994 const int kernelRadius = 1; 995 const int faultyLimit = 6; 996 int faultyPixels; 997 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 998 999 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage; 1000 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage; 1001 log << TestLog::Message << faultyLimit << " faulty pixels are allowed." << TestLog::EndMessage; 1002 faultyPixels = compareColoredImages(log, testImageAccess, referenceImageAccess, diffMask.getAccess(), kernelRadius); 1003 1004 if (faultyPixels > faultyLimit) 1005 { 1006 log << TestLog::ImageSet("Images", "Image comparison") 1007 << TestLog::Image("TestImage", "Test image", testImageAccess) 1008 << TestLog::Image("ReferenceImage", "Reference image", referenceImageAccess) 1009 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess()) 1010 << TestLog::EndImageSet 1011 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage; 1012 1013 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 1014 } 1015 } 1016 else 1017 { 1018 const float threshold = 0.3f; 1019 if (!tcu::fuzzyCompare(log, "Images", "", referenceImageAccess, testImageAccess, threshold, tcu::COMPARE_LOG_ON_ERROR)) 1020 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 1021 } 1022 } 1023 1024 class FillTest : public RenderTestCase 1025 { 1026 public: 1027 FillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport); 1028 1029 virtual void render (sglr::Context& ctx) = DE_NULL; 1030 void testRender (void); 1031 1032 protected: 1033 const rr::WindowRectangle m_viewport; 1034 }; 1035 1036 FillTest::FillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport) 1037 : RenderTestCase(context, name, description) 1038 , m_viewport (viewport) 1039 { 1040 } 1041 1042 void FillTest::testRender (void) 1043 { 1044 using tcu::TestLog; 1045 1046 const int numSamples = 1; 1047 1048 tcu::TestLog& log = m_testCtx.getLog(); 1049 sglr::GLContext glesContext (m_context.getRenderContext(), log, 0, tcu::IVec4(0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE)); 1050 sglr::ReferenceContextLimits limits; 1051 sglr::ReferenceContextBuffers buffers (m_context.getRenderTarget().getPixelFormat(), m_context.getRenderTarget().getDepthBits(), 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE, numSamples); 1052 sglr::ReferenceContext refContext (limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); 1053 tcu::Surface testSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1054 tcu::Surface refSurface (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1055 1056 render(glesContext); 1057 glesContext.readPixels(testSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1058 1059 render(refContext); 1060 refContext.readPixels(refSurface, 0, 0, TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1061 1062 // check overdraw 1063 { 1064 bool overdrawOk; 1065 tcu::Surface outputImage(TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1066 1067 log << TestLog::Message << "Checking for overdraw " << TestLog::EndMessage; 1068 overdrawOk = checkHalfFilledImageOverdraw(log, m_context.getRenderTarget(), testSurface.getAccess(), outputImage.getAccess()); 1069 1070 if (!overdrawOk) 1071 { 1072 log << TestLog::ImageSet("Images", "Image comparison") 1073 << TestLog::Image("TestImage", "Test image", testSurface.getAccess()) 1074 << TestLog::Image("InvalidPixels", "Invalid pixels", outputImage.getAccess()) 1075 << TestLog::EndImageSet 1076 << tcu::TestLog::Message << "Got overdraw." << tcu::TestLog::EndMessage; 1077 1078 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got overdraw"); 1079 } 1080 } 1081 1082 // compare & check missing pixels 1083 { 1084 const int kernelRadius = 1; 1085 tcu::Surface diffMask (TEST_CANVAS_SIZE, TEST_CANVAS_SIZE); 1086 int faultyPixels; 1087 1088 log << TestLog::Message << "Comparing images... " << TestLog::EndMessage; 1089 log << TestLog::Message << "Deviation within radius of " << kernelRadius << " is allowed." << TestLog::EndMessage; 1090 1091 blitImageOnBlackSurface(refSurface.getAccess(), refSurface.getAccess()); // makes images look right in Candy 1092 1093 faultyPixels = compareBlackNonBlackImages(log, testSurface.getAccess(), refSurface.getAccess(), diffMask.getAccess(), kernelRadius); 1094 1095 if (faultyPixels > 0) 1096 { 1097 log << TestLog::ImageSet("Images", "Image comparison") 1098 << TestLog::Image("TestImage", "Test image", testSurface.getAccess()) 1099 << TestLog::Image("ReferenceImage", "Reference image", refSurface.getAccess()) 1100 << TestLog::Image("DifferenceMask", "Difference mask", diffMask.getAccess()) 1101 << TestLog::EndImageSet 1102 << tcu::TestLog::Message << "Got " << faultyPixels << " faulty pixel(s)." << tcu::TestLog::EndMessage; 1103 1104 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got faulty pixels"); 1105 } 1106 } 1107 } 1108 1109 class TriangleFillTest : public FillTest 1110 { 1111 public: 1112 struct FillTriangle 1113 { 1114 tcu::Vec4 v0; 1115 tcu::Vec4 c0; 1116 tcu::Vec4 v1; 1117 tcu::Vec4 c1; 1118 tcu::Vec4 v2; 1119 tcu::Vec4 c2; 1120 }; 1121 1122 TriangleFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport); 1123 1124 void render (sglr::Context& ctx); 1125 1126 protected: 1127 std::vector<FillTriangle> m_triangles; 1128 }; 1129 1130 TriangleFillTest::TriangleFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport) 1131 : FillTest(context, name, description, viewport) 1132 { 1133 } 1134 1135 void TriangleFillTest::render (sglr::Context& ctx) 1136 { 1137 const int verticesPerTriangle = 3; 1138 PositionColorShader program; 1139 const deUint32 programId = ctx.createProgram(&program); 1140 const GLint positionLoc = ctx.getAttribLocation(programId, "a_position"); 1141 const GLint colorLoc = ctx.getAttribLocation(programId, "a_color"); 1142 tcu::TestLog& log = m_testCtx.getLog(); 1143 1144 // log the purpose of the test 1145 log << TestLog::Message << "Viewport: left=" << m_viewport.left << "\tbottom=" << m_viewport.bottom << "\twidth=" << m_viewport.width << "\theight=" << m_viewport.height << TestLog::EndMessage; 1146 log << TestLog::Message << "Rendering triangles. Coordinates:" << TestLog::EndMessage; 1147 for (size_t ndx = 0; ndx < m_triangles.size(); ++ndx) 1148 { 1149 const std::string v0Properties = genClippingPointInfoString(m_triangles[ndx].v0); 1150 const std::string v1Properties = genClippingPointInfoString(m_triangles[ndx].v1); 1151 const std::string v2Properties = genClippingPointInfoString(m_triangles[ndx].v2); 1152 1153 log << TestLog::Message << "\tv0 (x=" << m_triangles[ndx].v0.x() << "\ty=" << m_triangles[ndx].v0.y() << "\tz=" << m_triangles[ndx].v0.z() << "\tw=" << m_triangles[ndx].v0.w() << ")\t" << v0Properties << TestLog::EndMessage; 1154 log << TestLog::Message << "\tv1 (x=" << m_triangles[ndx].v1.x() << "\ty=" << m_triangles[ndx].v1.y() << "\tz=" << m_triangles[ndx].v1.z() << "\tw=" << m_triangles[ndx].v1.w() << ")\t" << v1Properties << TestLog::EndMessage; 1155 log << TestLog::Message << "\tv2 (x=" << m_triangles[ndx].v2.x() << "\ty=" << m_triangles[ndx].v2.y() << "\tz=" << m_triangles[ndx].v2.z() << "\tw=" << m_triangles[ndx].v2.w() << ")\t" << v2Properties << TestLog::EndMessage; 1156 log << TestLog::Message << TestLog::EndMessage; 1157 } 1158 1159 ctx.clearColor (0, 0, 0, 1); 1160 ctx.clearDepthf (1.0f); 1161 ctx.clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1162 ctx.viewport (m_viewport.left, m_viewport.bottom, m_viewport.width, m_viewport.height); 1163 ctx.useProgram (programId); 1164 ctx.blendFunc (GL_ONE, GL_ONE); 1165 ctx.enable (GL_BLEND); 1166 ctx.enableVertexAttribArray (positionLoc); 1167 ctx.enableVertexAttribArray (colorLoc); 1168 ctx.vertexAttribPointer (positionLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_triangles[0].v0); 1169 ctx.vertexAttribPointer (colorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat[8]), &m_triangles[0].c0); 1170 ctx.drawArrays (GL_TRIANGLES, 0, verticesPerTriangle * (glw::GLsizei)m_triangles.size()); 1171 ctx.disableVertexAttribArray (positionLoc); 1172 ctx.disableVertexAttribArray (colorLoc); 1173 ctx.useProgram (0); 1174 ctx.deleteProgram (programId); 1175 ctx.finish (); 1176 } 1177 1178 class QuadFillTest : public TriangleFillTest 1179 { 1180 public: 1181 QuadFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport, const tcu::Vec3& d1, const tcu::Vec3& d2, const tcu::Vec3& center_ = tcu::Vec3(0, 0, 0)); 1182 }; 1183 1184 QuadFillTest::QuadFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport, const tcu::Vec3& d1, const tcu::Vec3& d2, const tcu::Vec3& center_) 1185 : TriangleFillTest(context, name, description, viewport) 1186 { 1187 const float radius = 40000.0f; 1188 const tcu::Vec4 center = tcu::Vec4(center_.x(), center_.y(), center_.z(), 1.0f); 1189 const tcu::Vec4 halfWhite = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f); 1190 const tcu::Vec4 halfRed = tcu::Vec4(0.5f, 0.0f, 0.0f, 0.5f); 1191 const tcu::Vec4 e1 = radius * tcu::Vec4(d1.x(), d1.y(), d1.z(), 0.0f); 1192 const tcu::Vec4 e2 = radius * tcu::Vec4(d2.x(), d2.y(), d2.z(), 0.0f); 1193 1194 FillTriangle triangle1; 1195 FillTriangle triangle2; 1196 1197 triangle1.c0 = halfWhite; 1198 triangle1.c1 = halfWhite; 1199 triangle1.c2 = halfWhite; 1200 triangle1.v0 = center + e1 + e2; 1201 triangle1.v1 = center + e1 - e2; 1202 triangle1.v2 = center - e1 - e2; 1203 m_triangles.push_back(triangle1); 1204 1205 triangle2.c0 = halfRed; 1206 triangle2.c1 = halfRed; 1207 triangle2.c2 = halfRed; 1208 triangle2.v0 = center + e1 + e2; 1209 triangle2.v1 = center - e1 - e2; 1210 triangle2.v2 = center - e1 + e2; 1211 m_triangles.push_back(triangle2); 1212 } 1213 1214 class TriangleFanFillTest : public TriangleFillTest 1215 { 1216 public: 1217 TriangleFanFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport); 1218 }; 1219 1220 TriangleFanFillTest::TriangleFanFillTest (Context& context, const char* name, const char* description, const rr::WindowRectangle& viewport) 1221 : TriangleFillTest(context, name, description, viewport) 1222 { 1223 const float radius = 70000.0f; 1224 const int trianglesPerVisit = 40; 1225 const tcu::Vec4 center = tcu::Vec4(0, 0, 0, 1.0f); 1226 const tcu::Vec4 halfWhite = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f); 1227 const tcu::Vec4 oddSliceColor = tcu::Vec4(0.0f, 0.0f, 0.5f, 0.0f); 1228 1229 // create a continuous surface that goes through all 6 clip planes 1230 1231 /* 1232 * / / 1233 * /_ _ _ _ _ /x 1234 * | | | 1235 * | | / 1236 * | / --xe / 1237 * | | | / 1238 * |_ _ _ e _ _|/ 1239 * 1240 * e = enter 1241 * x = exit 1242 */ 1243 const struct ClipPlaneVisit 1244 { 1245 const tcu::Vec3 corner; 1246 const tcu::Vec3 entryPoint; 1247 const tcu::Vec3 exitPoint; 1248 } visits[] = 1249 { 1250 { tcu::Vec3( 1, 1, 1), tcu::Vec3( 0, 1, 1), tcu::Vec3( 1, 0, 1) }, 1251 { tcu::Vec3( 1,-1, 1), tcu::Vec3( 1, 0, 1), tcu::Vec3( 1,-1, 0) }, 1252 { tcu::Vec3( 1,-1,-1), tcu::Vec3( 1,-1, 0), tcu::Vec3( 0,-1,-1) }, 1253 { tcu::Vec3(-1,-1,-1), tcu::Vec3( 0,-1,-1), tcu::Vec3(-1, 0,-1) }, 1254 { tcu::Vec3(-1, 1,-1), tcu::Vec3(-1, 0,-1), tcu::Vec3(-1, 1, 0) }, 1255 { tcu::Vec3(-1, 1, 1), tcu::Vec3(-1, 1, 0), tcu::Vec3( 0, 1, 1) }, 1256 }; 1257 1258 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(visits); ++ndx) 1259 { 1260 const ClipPlaneVisit& visit = visits[ndx]; 1261 1262 for (int tri = 0; tri < trianglesPerVisit; ++tri) 1263 { 1264 tcu::Vec3 vertex0; 1265 tcu::Vec3 vertex1; 1266 1267 if (tri == 0) // first vertex is magic 1268 { 1269 vertex0 = visit.entryPoint; 1270 } 1271 else 1272 { 1273 const tcu::Vec3 v1 = visit.entryPoint - visit.corner; 1274 const tcu::Vec3 v2 = visit.exitPoint - visit.corner; 1275 1276 vertex0 = visit.corner + tcu::normalize(tcu::mix(v1, v2, tcu::Vec3(float(tri)/trianglesPerVisit))); 1277 } 1278 1279 if (tri == trianglesPerVisit-1) // last vertex is magic 1280 { 1281 vertex1 = visit.exitPoint; 1282 } 1283 else 1284 { 1285 const tcu::Vec3 v1 = visit.entryPoint - visit.corner; 1286 const tcu::Vec3 v2 = visit.exitPoint - visit.corner; 1287 1288 vertex1 = visit.corner + tcu::normalize(tcu::mix(v1, v2, tcu::Vec3(float(tri+1)/trianglesPerVisit))); 1289 } 1290 1291 // write vec out 1292 { 1293 FillTriangle triangle; 1294 1295 triangle.c0 = (tri % 2) ? halfWhite : halfWhite + oddSliceColor; 1296 triangle.c1 = (tri % 2) ? halfWhite : halfWhite + oddSliceColor; 1297 triangle.c2 = (tri % 2) ? halfWhite : halfWhite + oddSliceColor; 1298 triangle.v0 = center; 1299 triangle.v1 = tcu::Vec4(vertex0.x() * radius, vertex0.y() * radius, vertex0.z() * radius, 1.0f); 1300 triangle.v2 = tcu::Vec4(vertex1.x() * radius, vertex1.y() * radius, vertex1.z() * radius, 1.0f); 1301 1302 m_triangles.push_back(triangle); 1303 } 1304 1305 } 1306 } 1307 } 1308 1309 class PointsTestGroup : public TestCaseGroup 1310 { 1311 public: 1312 PointsTestGroup (Context& context); 1313 1314 void init (void); 1315 }; 1316 1317 PointsTestGroup::PointsTestGroup (Context& context) 1318 : TestCaseGroup(context, "point", "Point clipping tests") 1319 { 1320 } 1321 1322 void PointsTestGroup::init (void) 1323 { 1324 const float littleOverViewport = 1.0f + (2.0f / (TEST_CANVAS_SIZE)); // one pixel over the viewport edge in VIEWPORT_WHOLE, half pixels over in the reduced viewport. 1325 1326 const tcu::Vec4 viewportTestPoints[] = 1327 { 1328 // in clip volume 1329 tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), 1330 tcu::Vec4( 0.1f, 0.1f, 0.1f, 1.0f), 1331 tcu::Vec4(-0.1f, 0.1f, -0.1f, 1.0f), 1332 tcu::Vec4(-0.1f, -0.1f, 0.1f, 1.0f), 1333 tcu::Vec4( 0.1f, -0.1f, -0.1f, 1.0f), 1334 1335 // in clip volume with w != 1 1336 tcu::Vec4( 2.0f, 2.0f, 2.0f, 3.0f), 1337 tcu::Vec4(-2.0f, -2.0f, 2.0f, 3.0f), 1338 tcu::Vec4( 0.5f, -0.5f, 0.5f, 0.7f), 1339 tcu::Vec4(-0.5f, 0.5f, -0.5f, 0.7f), 1340 1341 // near the edge 1342 tcu::Vec4(-2.0f, -2.0f, 0.0f, 2.2f), 1343 tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.1f), 1344 tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.1f), 1345 1346 // not in the volume but still between near and far planes 1347 tcu::Vec4( 1.3f, 0.0f, 0.0f, 1.0f), 1348 tcu::Vec4(-1.3f, 0.0f, 0.0f, 1.0f), 1349 tcu::Vec4( 0.0f, 1.3f, 0.0f, 1.0f), 1350 tcu::Vec4( 0.0f, -1.3f, 0.0f, 1.0f), 1351 1352 tcu::Vec4(-1.3f, -1.3f, 0.0f, 1.0f), 1353 tcu::Vec4(-1.3f, 1.3f, 0.0f, 1.0f), 1354 tcu::Vec4( 1.3f, 1.3f, 0.0f, 1.0f), 1355 tcu::Vec4( 1.3f, -1.3f, 0.0f, 1.0f), 1356 1357 // outside the viewport, wide points have fragments in the viewport 1358 tcu::Vec4( littleOverViewport, littleOverViewport, 0.0f, 1.0f), 1359 tcu::Vec4( 0.0f, littleOverViewport, 0.0f, 1.0f), 1360 tcu::Vec4( littleOverViewport, 0.0f, 0.0f, 1.0f), 1361 }; 1362 const tcu::Vec4 depthTestPoints[] = 1363 { 1364 // in clip volume 1365 tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), 1366 tcu::Vec4( 0.1f, 0.1f, 0.1f, 1.0f), 1367 tcu::Vec4(-0.1f, 0.1f, -0.1f, 1.0f), 1368 tcu::Vec4(-0.1f, -0.1f, 0.1f, 1.0f), 1369 tcu::Vec4( 0.1f, -0.1f, -0.1f, 1.0f), 1370 1371 // not between the near and the far planes. These should be clipped 1372 tcu::Vec4( 0.1f, 0.0f, 1.1f, 1.0f), 1373 tcu::Vec4(-0.1f, 0.0f, -1.1f, 1.0f), 1374 tcu::Vec4(-0.0f, -0.1f, 1.1f, 1.0f), 1375 tcu::Vec4( 0.0f, 0.1f, -1.1f, 1.0f) 1376 }; 1377 1378 addChild(new PointCase(m_context, "point_z_clip", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 1.0f, VIEWPORT_WHOLE)); 1379 addChild(new PointCase(m_context, "point_z_clip_viewport_center", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 1.0f, VIEWPORT_CENTER)); 1380 addChild(new PointCase(m_context, "point_z_clip_viewport_corner", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 1.0f, VIEWPORT_CORNER)); 1381 1382 addChild(new PointCase(m_context, "point_clip_viewport_center", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 1.0f, VIEWPORT_CENTER)); 1383 addChild(new PointCase(m_context, "point_clip_viewport_corner", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 1.0f, VIEWPORT_CORNER)); 1384 1385 addChild(new PointCase(m_context, "wide_point_z_clip", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 5.0f, VIEWPORT_WHOLE)); 1386 addChild(new PointCase(m_context, "wide_point_z_clip_viewport_center", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 5.0f, VIEWPORT_CENTER)); 1387 addChild(new PointCase(m_context, "wide_point_z_clip_viewport_corner", "point z clipping", DE_ARRAY_BEGIN(depthTestPoints), DE_ARRAY_END(depthTestPoints), 5.0f, VIEWPORT_CORNER)); 1388 1389 addChild(new PointCase(m_context, "wide_point_clip", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 5.0f, VIEWPORT_WHOLE)); 1390 addChild(new PointCase(m_context, "wide_point_clip_viewport_center", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 5.0f, VIEWPORT_CENTER)); 1391 addChild(new PointCase(m_context, "wide_point_clip_viewport_corner", "point viewport clipping", DE_ARRAY_BEGIN(viewportTestPoints), DE_ARRAY_END(viewportTestPoints), 5.0f, VIEWPORT_CORNER)); 1392 } 1393 1394 class LinesTestGroup : public TestCaseGroup 1395 { 1396 public: 1397 LinesTestGroup (Context& context); 1398 1399 void init (void); 1400 }; 1401 1402 LinesTestGroup::LinesTestGroup (Context& context) 1403 : TestCaseGroup(context, "line", "Line clipping tests") 1404 { 1405 } 1406 1407 void LinesTestGroup::init (void) 1408 { 1409 const float littleOverViewport = 1.0f + (2.0f / (TEST_CANVAS_SIZE)); // one pixel over the viewport edge in VIEWPORT_WHOLE, half pixels over in the reduced viewport. 1410 1411 // lines 1412 const LineRenderTestCase::ColorlessLineData viewportTestLines[] = 1413 { 1414 // from center to outside of viewport 1415 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.0f, 1.5f, 0.0f, 1.0f)}, 1416 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.5f, 1.0f, 0.0f, 1.0f)}, 1417 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.5f, 0.0f, 0.0f, 1.0f)}, 1418 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.2f, 0.4f, 1.5f, 1.0f)}, 1419 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-2.0f, -1.0f, 0.0f, 1.0f)}, 1420 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.0f, 0.1f, 0.0f, 0.6f)}, 1421 1422 // from outside to inside of viewport 1423 {tcu::Vec4( 1.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.8f, -0.2f, 0.0f, 1.0f)}, 1424 {tcu::Vec4( 0.0f, -1.5f, 0.0f, 1.0f), tcu::Vec4( 0.9f, -0.7f, 0.0f, 1.0f)}, 1425 1426 // from outside to outside 1427 {tcu::Vec4( 0.0f, -1.3f, 0.0f, 1.0f), tcu::Vec4( 1.3f, 0.0f, 0.0f, 1.0f)}, 1428 1429 // outside the viewport, wide lines have fragments in the viewport 1430 {tcu::Vec4(-0.8f, -littleOverViewport, 0.0f, 1.0f), tcu::Vec4( 0.0f, -littleOverViewport, 0.0f, 1.0f)}, 1431 {tcu::Vec4(-littleOverViewport - 1.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 0.0f, -littleOverViewport - 1.0f, 0.0f, 1.0f)}, 1432 }; 1433 const LineRenderTestCase::ColorlessLineData depthTestLines[] = 1434 { 1435 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.3f, 1.0f, 2.0f, 1.0f)}, 1436 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.3f, -1.0f, 2.0f, 1.0f)}, 1437 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.0f, -1.1f, -2.0f, 1.0f)}, 1438 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(-1.0f, 1.1f, -2.0f, 1.0f)}, 1439 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4( 1.0f, 0.1f, 2.0f, 0.6f)}, 1440 }; 1441 const LineRenderTestCase::ColorlessLineData longTestLines[] = 1442 { 1443 {tcu::Vec4( -41000.0f, -40000.0f, -1000000.0f, 1.0f), tcu::Vec4( 41000.0f, 40000.0f, 1000000.0f, 1.0f)}, 1444 {tcu::Vec4( 41000.0f, -40000.0f, 1000000.0f, 1.0f), tcu::Vec4(-41000.0f, 40000.0f, -1000000.0f, 1.0f)}, 1445 {tcu::Vec4( 0.5f, -40000.0f, 100000.0f, 1.0f), tcu::Vec4( 0.5f, 40000.0f, -100000.0f, 1.0f)}, 1446 {tcu::Vec4( -0.5f, 40000.0f, 100000.0f, 1.0f), tcu::Vec4(-0.5f, -40000.0f, -100000.0f, 1.0f)}, 1447 }; 1448 1449 // line attribute clipping 1450 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); 1451 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f); 1452 const tcu::Vec4 lightBlue (0.3f, 0.3f, 1.0f, 1.0f); 1453 const LineRenderTestCase::ColoredLineData colorTestLines[] = 1454 { 1455 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.3f, 1.0f, 2.0f, 1.0f), yellow }, 1456 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.3f, -1.0f, 2.0f, 1.0f), lightBlue }, 1457 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4(-1.0f, -1.0f, -2.0f, 1.0f), yellow }, 1458 {tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f), red, tcu::Vec4(-1.0f, 1.0f, -2.0f, 1.0f), lightBlue }, 1459 }; 1460 1461 // line clipping 1462 addChild(new LineCase(m_context, "line_z_clip", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 1.0f, VIEWPORT_WHOLE)); 1463 addChild(new LineCase(m_context, "line_z_clip_viewport_center", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 1.0f, VIEWPORT_CENTER)); 1464 addChild(new LineCase(m_context, "line_z_clip_viewport_corner", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 1.0f, VIEWPORT_CORNER)); 1465 1466 addChild(new LineCase(m_context, "line_clip_viewport_center", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 1.0f, VIEWPORT_CENTER)); 1467 addChild(new LineCase(m_context, "line_clip_viewport_corner", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 1.0f, VIEWPORT_CORNER)); 1468 1469 addChild(new LineCase(m_context, "wide_line_z_clip", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 5.0f, VIEWPORT_WHOLE)); 1470 addChild(new LineCase(m_context, "wide_line_z_clip_viewport_center", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 5.0f, VIEWPORT_CENTER)); 1471 addChild(new LineCase(m_context, "wide_line_z_clip_viewport_corner", "line z clipping", DE_ARRAY_BEGIN(depthTestLines), DE_ARRAY_END(depthTestLines), 5.0f, VIEWPORT_CORNER)); 1472 1473 addChild(new LineCase(m_context, "wide_line_clip", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 5.0f, VIEWPORT_WHOLE)); 1474 addChild(new LineCase(m_context, "wide_line_clip_viewport_center", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 5.0f, VIEWPORT_CENTER)); 1475 addChild(new LineCase(m_context, "wide_line_clip_viewport_corner", "line viewport clipping", DE_ARRAY_BEGIN(viewportTestLines), DE_ARRAY_END(viewportTestLines), 5.0f, VIEWPORT_CORNER)); 1476 1477 addChild(new LineCase(m_context, "long_line_clip", "line viewport clipping", DE_ARRAY_BEGIN(longTestLines), DE_ARRAY_END(longTestLines), 1.0f, VIEWPORT_WHOLE, 2)); 1478 addChild(new LineCase(m_context, "long_wide_line_clip", "line viewport clipping", DE_ARRAY_BEGIN(longTestLines), DE_ARRAY_END(longTestLines), 5.0f, VIEWPORT_WHOLE, 2)); 1479 1480 // line attribute clipping 1481 addChild(new ColoredLineCase(m_context, "line_attrib_clip", "line attribute clipping", DE_ARRAY_BEGIN(colorTestLines), DE_ARRAY_END(colorTestLines), 1.0f, VIEWPORT_WHOLE)); 1482 addChild(new ColoredLineCase(m_context, "wide_line_attrib_clip", "line attribute clipping", DE_ARRAY_BEGIN(colorTestLines), DE_ARRAY_END(colorTestLines), 5.0f, VIEWPORT_WHOLE)); 1483 } 1484 1485 class PolysTestGroup : public TestCaseGroup 1486 { 1487 public: 1488 PolysTestGroup (Context& context); 1489 1490 void init (void); 1491 }; 1492 1493 PolysTestGroup::PolysTestGroup (Context& context) 1494 : TestCaseGroup(context, "polygon", "Polygon clipping tests") 1495 { 1496 } 1497 1498 void PolysTestGroup::init (void) 1499 { 1500 const float large = 100000.0f; 1501 const float offset = 0.9f; 1502 const tcu::Vec4 white (1.0f, 1.0f, 1.0f, 1.0f); 1503 const tcu::Vec4 red (1.0f, 0.0f, 0.0f, 1.0f); 1504 const tcu::Vec4 yellow (1.0f, 1.0f, 0.0f, 1.0f); 1505 const tcu::Vec4 blue (0.0f, 0.0f, 1.0f, 1.0f); 1506 1507 // basic cases 1508 { 1509 const TriangleCase::TriangleData viewportPolys[] = 1510 { 1511 // one vertex clipped 1512 {tcu::Vec4(-0.8f, -0.2f, 0.0f, 1.0f), white, tcu::Vec4(-0.8f, 0.2f, 0.0f, 1.0f), white, tcu::Vec4(-1.3f, 0.05f, 0.0f, 1.0f), white}, 1513 1514 // two vertices clipped 1515 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), white, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), white, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), white}, 1516 1517 // three vertices clipped 1518 {tcu::Vec4(-1.1f, 0.6f, 0.0f, 1.0f), white, tcu::Vec4(-1.1f, 1.1f, 0.0f, 1.0f), white, tcu::Vec4(-0.6f, 1.1f, 0.0f, 1.0f), white}, 1519 {tcu::Vec4( 0.8f, 1.1f, 0.0f, 1.0f), white, tcu::Vec4( 0.95f,-1.1f, 0.0f, 1.0f), white, tcu::Vec4( 3.0f, 0.0f, 0.0f, 1.0f), white}, 1520 }; 1521 const TriangleCase::TriangleData depthPolys[] = 1522 { 1523 // one vertex clipped to Z+ 1524 {tcu::Vec4(-0.2f, 0.7f, 0.0f, 1.0f), white, tcu::Vec4( 0.2f, 0.7f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, 0.9f, 2.0f, 1.0f), white}, 1525 1526 // two vertices clipped to Z- 1527 {tcu::Vec4( 0.9f, 0.4f, -1.5f, 1.0f), white, tcu::Vec4( 0.9f, -0.4f, -1.5f, 1.0f), white, tcu::Vec4( 0.6f, 0.0f, 0.0f, 1.0f), white}, 1528 1529 // three vertices clipped 1530 {tcu::Vec4(-0.9f, 0.6f, -2.0f, 1.0f), white, tcu::Vec4(-0.9f, -0.6f, -2.0f, 1.0f), white, tcu::Vec4(-0.4f, 0.0f, 2.0f, 1.0f), white}, 1531 1532 // three vertices clipped by X, Y and Z 1533 {tcu::Vec4( 0.0f, -1.2f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, 0.5f, -1.5f, 1.0f), white, tcu::Vec4( 1.2f, -0.9f, 0.0f, 1.0f), white}, 1534 }; 1535 const TriangleCase::TriangleData largePolys[] = 1536 { 1537 // one vertex clipped 1538 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, -large, 2.0f, 1.0f), white}, 1539 1540 // two vertices clipped 1541 {tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f), white, tcu::Vec4( large, 0.5f, 0.0f, 1.0f), white, tcu::Vec4( 0.5f, large, 0.0f, 1.0f), white}, 1542 1543 // three vertices clipped 1544 {tcu::Vec4(-0.9f, -large, 0.0f, 1.0f), white, tcu::Vec4(-1.1f, -large, 0.0f, 1.0f), white, tcu::Vec4(-0.9f, large, 0.0f, 1.0f), white}, 1545 }; 1546 const TriangleCase::TriangleData largeDepthPolys[] = 1547 { 1548 // one vertex clipped 1549 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), white, tcu::Vec4( 0.0f, -large, large, 1.0f), white}, 1550 1551 // two vertices clipped 1552 {tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f), white, tcu::Vec4( 0.9f, large/2, -large, 1.0f), white, tcu::Vec4( large/4, 0.0f, -large, 1.0f), white}, 1553 1554 // three vertices clipped 1555 {tcu::Vec4(-0.9f, large/4, large, 1.0f), white, tcu::Vec4(-0.5f, -large/4, -large, 1.0f), white, tcu::Vec4(-0.2f, large/4, large, 1.0f), white}, 1556 }; 1557 const TriangleCase::TriangleData attribPolys[] = 1558 { 1559 // one vertex clipped to edge, large 1560 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -large, 2.0f, 1.0f), blue}, 1561 1562 // two vertices clipped to edges 1563 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1564 1565 // two vertices clipped to edges, with non-uniform w 1566 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1567 1568 // three vertices clipped, large, Z 1569 {tcu::Vec4(-0.9f, large/4, large, 1.0f), red, tcu::Vec4(-0.5f, -large/4, -large, 1.0f), yellow, tcu::Vec4(-0.2f, large/4, large, 1.0f), blue}, 1570 }; 1571 1572 addChild(new TriangleCase(m_context, "poly_clip_viewport_center", "polygon viewport clipping", DE_ARRAY_BEGIN(viewportPolys), DE_ARRAY_END(viewportPolys), VIEWPORT_CENTER)); 1573 addChild(new TriangleCase(m_context, "poly_clip_viewport_corner", "polygon viewport clipping", DE_ARRAY_BEGIN(viewportPolys), DE_ARRAY_END(viewportPolys), VIEWPORT_CORNER)); 1574 1575 addChild(new TriangleCase(m_context, "poly_z_clip", "polygon z clipping", DE_ARRAY_BEGIN(depthPolys), DE_ARRAY_END(depthPolys), VIEWPORT_WHOLE)); 1576 addChild(new TriangleCase(m_context, "poly_z_clip_viewport_center", "polygon z clipping", DE_ARRAY_BEGIN(depthPolys), DE_ARRAY_END(depthPolys), VIEWPORT_CENTER)); 1577 addChild(new TriangleCase(m_context, "poly_z_clip_viewport_corner", "polygon z clipping", DE_ARRAY_BEGIN(depthPolys), DE_ARRAY_END(depthPolys), VIEWPORT_CORNER)); 1578 1579 addChild(new TriangleCase(m_context, "large_poly_clip_viewport_center", "polygon viewport clipping", DE_ARRAY_BEGIN(largePolys), DE_ARRAY_END(largePolys), VIEWPORT_CENTER)); 1580 addChild(new TriangleCase(m_context, "large_poly_clip_viewport_corner", "polygon viewport clipping", DE_ARRAY_BEGIN(largePolys), DE_ARRAY_END(largePolys), VIEWPORT_CORNER)); 1581 1582 addChild(new TriangleCase(m_context, "large_poly_z_clip", "polygon z clipping", DE_ARRAY_BEGIN(largeDepthPolys), DE_ARRAY_END(largeDepthPolys), VIEWPORT_WHOLE)); 1583 addChild(new TriangleCase(m_context, "large_poly_z_clip_viewport_center", "polygon z clipping", DE_ARRAY_BEGIN(largeDepthPolys), DE_ARRAY_END(largeDepthPolys), VIEWPORT_CENTER)); 1584 addChild(new TriangleCase(m_context, "large_poly_z_clip_viewport_corner", "polygon z clipping", DE_ARRAY_BEGIN(largeDepthPolys), DE_ARRAY_END(largeDepthPolys), VIEWPORT_CORNER)); 1585 1586 addChild(new TriangleAttributeCase(m_context, "poly_attrib_clip", "polygon clipping", DE_ARRAY_BEGIN(attribPolys), DE_ARRAY_END(attribPolys), VIEWPORT_WHOLE)); 1587 addChild(new TriangleAttributeCase(m_context, "poly_attrib_clip_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(attribPolys), DE_ARRAY_END(attribPolys), VIEWPORT_CENTER)); 1588 addChild(new TriangleAttributeCase(m_context, "poly_attrib_clip_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(attribPolys), DE_ARRAY_END(attribPolys), VIEWPORT_CORNER)); 1589 } 1590 1591 // multiple polygons 1592 { 1593 { 1594 const TriangleAttributeCase::TriangleData polys[] = 1595 { 1596 // one vertex clipped to edge 1597 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue}, 1598 1599 // two vertices clipped to edges 1600 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1601 1602 // two vertices clipped to edges, with non-uniform w 1603 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1604 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1605 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1606 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1607 1608 // three vertices clipped, Z 1609 {tcu::Vec4(-0.9f, offset/4, offset, 1.0f), red, tcu::Vec4(-0.5f, -offset/4, -offset, 1.0f), yellow, tcu::Vec4(-0.2f, offset/4, offset, 1.0f), blue}, 1610 }; 1611 1612 addChild(new TriangleAttributeCase(m_context, "multiple_0", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1613 addChild(new TriangleAttributeCase(m_context, "multiple_0_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1614 addChild(new TriangleAttributeCase(m_context, "multiple_0_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1615 } 1616 1617 { 1618 const TriangleAttributeCase::TriangleData polys[] = 1619 { 1620 // one vertex clipped to z 1621 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue}, 1622 1623 // two vertices clipped to edges 1624 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1625 1626 // two vertices clipped to edges, with non-uniform w 1627 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1628 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1629 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1630 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, 16.0f*tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1631 }; 1632 1633 addChild(new TriangleAttributeCase(m_context, "multiple_1", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1634 addChild(new TriangleAttributeCase(m_context, "multiple_1_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1635 addChild(new TriangleAttributeCase(m_context, "multiple_1_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1636 } 1637 1638 { 1639 const TriangleAttributeCase::TriangleData polys[] = 1640 { 1641 // one vertex clipped to z 1642 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue}, 1643 1644 // two vertices clipped to edges 1645 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1646 1647 // two vertices clipped to edges 1648 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1649 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1650 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1651 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1652 }; 1653 1654 addChild(new TriangleAttributeCase(m_context, "multiple_2", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1655 addChild(new TriangleAttributeCase(m_context, "multiple_2_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1656 addChild(new TriangleAttributeCase(m_context, "multiple_2_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1657 } 1658 1659 { 1660 const TriangleAttributeCase::TriangleData polys[] = 1661 { 1662 // one vertex clipped to z 1663 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, -2.0f, 1.0f), blue}, 1664 1665 // two vertices clipped to edges 1666 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1667 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1668 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1669 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1670 }; 1671 1672 addChild(new TriangleAttributeCase(m_context, "multiple_3", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1673 addChild(new TriangleAttributeCase(m_context, "multiple_3_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1674 addChild(new TriangleAttributeCase(m_context, "multiple_3_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1675 } 1676 1677 { 1678 const TriangleAttributeCase::TriangleData polys[] = 1679 { 1680 // one vertex clipped to z 1681 {tcu::Vec4(0.3f, 0.2f, 0.0f, 1.0f), red, tcu::Vec4( 0.3f, -0.2f, 0.0f, 1.0f), yellow, tcu::Vec4( offset, 0.0f, 2.0f, 1.0f), blue}, 1682 1683 // two vertices clipped to edges 1684 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1685 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1686 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1687 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1688 }; 1689 1690 addChild(new TriangleAttributeCase(m_context, "multiple_4", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1691 addChild(new TriangleAttributeCase(m_context, "multiple_4_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1692 addChild(new TriangleAttributeCase(m_context, "multiple_4_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1693 } 1694 1695 { 1696 const TriangleAttributeCase::TriangleData polys[] = 1697 { 1698 // one vertex clipped to z 1699 {tcu::Vec4(-0.3f, 0.2f, 0.0f, 1.0f), red, tcu::Vec4(-0.3f, -0.2f, 0.0f, 1.0f), yellow, tcu::Vec4(-offset, 0.0f, 2.0f, 1.0f), blue}, 1700 1701 // two vertices clipped to edges 1702 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1703 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1704 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1705 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1706 }; 1707 1708 addChild(new TriangleAttributeCase(m_context, "multiple_5", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1709 addChild(new TriangleAttributeCase(m_context, "multiple_5_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1710 addChild(new TriangleAttributeCase(m_context, "multiple_5_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1711 } 1712 1713 { 1714 const TriangleAttributeCase::TriangleData polys[] = 1715 { 1716 // one vertex clipped to z 1717 {tcu::Vec4(-0.2f, 0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, 0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, offset, 2.0f, 1.0f), blue}, 1718 1719 // two vertices clipped to edges 1720 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1721 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1722 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1723 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1724 }; 1725 1726 addChild(new TriangleAttributeCase(m_context, "multiple_6", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1727 addChild(new TriangleAttributeCase(m_context, "multiple_6_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1728 addChild(new TriangleAttributeCase(m_context, "multiple_6_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1729 } 1730 1731 { 1732 const TriangleAttributeCase::TriangleData polys[] = 1733 { 1734 // two vertices clipped to edges 1735 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1736 1737 // two vertices clipped to edges 1738 {tcu::Vec4( 0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, -0.6f, 0.0f, 1.0f), blue}, 1739 {tcu::Vec4( 0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4( 1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.6f, 0.6f, 0.0f, 1.0f), blue}, 1740 {tcu::Vec4(-0.6f, 1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, 0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, 0.6f, 0.0f, 1.0f), blue}, 1741 {tcu::Vec4(-0.6f, -1.2f, 0.0f, 1.0f), red, tcu::Vec4(-1.2f, -0.6f, 0.0f, 1.0f), yellow, tcu::Vec4(-0.6f, -0.6f, 0.0f, 1.0f), blue}, 1742 }; 1743 1744 addChild(new TriangleAttributeCase(m_context, "multiple_7", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1745 addChild(new TriangleAttributeCase(m_context, "multiple_7_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1746 addChild(new TriangleAttributeCase(m_context, "multiple_7_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1747 } 1748 1749 { 1750 const TriangleAttributeCase::TriangleData polys[] = 1751 { 1752 // one vertex clipped to z 1753 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue}, 1754 1755 // fill 1756 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), white}, 1757 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), blue}, 1758 }; 1759 1760 addChild(new TriangleAttributeCase(m_context, "multiple_8", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1761 addChild(new TriangleAttributeCase(m_context, "multiple_8_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1762 addChild(new TriangleAttributeCase(m_context, "multiple_8_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1763 } 1764 1765 { 1766 const TriangleAttributeCase::TriangleData polys[] = 1767 { 1768 // one vertex clipped to z 1769 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue}, 1770 1771 // fill 1772 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), red}, 1773 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue}, 1774 }; 1775 1776 addChild(new TriangleAttributeCase(m_context, "multiple_9", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1777 addChild(new TriangleAttributeCase(m_context, "multiple_9_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1778 addChild(new TriangleAttributeCase(m_context, "multiple_9_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1779 } 1780 1781 { 1782 const TriangleAttributeCase::TriangleData polys[] = 1783 { 1784 // one vertex clipped to z 1785 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue}, 1786 1787 // fill 1788 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), white}, 1789 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), red}, 1790 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue}, 1791 }; 1792 1793 addChild(new TriangleAttributeCase(m_context, "multiple_10", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1794 addChild(new TriangleAttributeCase(m_context, "multiple_10_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1795 addChild(new TriangleAttributeCase(m_context, "multiple_10_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1796 } 1797 1798 { 1799 const TriangleAttributeCase::TriangleData polys[] = 1800 { 1801 // one vertex clipped to z 1802 {tcu::Vec4(-0.2f, -0.3f, 0.0f, 1.0f), red, tcu::Vec4( 0.2f, -0.3f, 0.0f, 1.0f), yellow, tcu::Vec4( 0.0f, -offset, 2.0f, 1.0f), blue}, 1803 1804 // fill 1805 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), white, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), white}, 1806 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), red, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), red}, 1807 {tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), blue, tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), blue}, 1808 {tcu::Vec4( -1.0f, 1.0f, 0.0f, 1.0f), yellow, tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), yellow, tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), yellow}, 1809 }; 1810 1811 addChild(new TriangleAttributeCase(m_context, "multiple_11", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_WHOLE)); 1812 addChild(new TriangleAttributeCase(m_context, "multiple_11_viewport_center", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CENTER)); 1813 addChild(new TriangleAttributeCase(m_context, "multiple_11_viewport_corner", "polygon clipping", DE_ARRAY_BEGIN(polys), DE_ARRAY_END(polys), VIEWPORT_CORNER)); 1814 } 1815 } 1816 } 1817 1818 class PolyEdgesTestGroup : public TestCaseGroup 1819 { 1820 public: 1821 PolyEdgesTestGroup (Context& context); 1822 1823 void init (void); 1824 }; 1825 1826 PolyEdgesTestGroup::PolyEdgesTestGroup (Context& context) 1827 : TestCaseGroup(context, "polygon_edge", "Polygon clipping edge tests") 1828 { 1829 } 1830 1831 void PolyEdgesTestGroup::init (void) 1832 { 1833 // Quads via origin 1834 const struct Quad 1835 { 1836 tcu::Vec3 d1; // tangent 1837 tcu::Vec3 d2; // bi-tangent 1838 } quads[] = 1839 { 1840 { tcu::Vec3( 1, 1, 1), tcu::Vec3( 1, -1, 1) }, 1841 { tcu::Vec3( 1, 1, 1), tcu::Vec3(-1, 1.1f, 1) }, 1842 { tcu::Vec3( 1, 1, 0), tcu::Vec3(-1, 1, 0) }, 1843 { tcu::Vec3( 0, 1, 0), tcu::Vec3( 1, 0, 0) }, 1844 { tcu::Vec3( 0, 1, 0), tcu::Vec3( 1, 0.1f, 0) }, 1845 }; 1846 1847 // Quad near edge 1848 const struct EdgeQuad 1849 { 1850 tcu::Vec3 d1; // tangent 1851 tcu::Vec3 d2; // bi-tangent 1852 tcu::Vec3 center; // center 1853 } edgeQuads[] = 1854 { 1855 { tcu::Vec3( 1, 0.01f, 0 ), tcu::Vec3( 0, 0.01f, 0), tcu::Vec3( 0, 0.99f, 0 ) }, // edge near x-plane 1856 { tcu::Vec3( 0.01f, 1, 0 ), tcu::Vec3( 0.01f, 0, 0), tcu::Vec3( 0.99f, 0, 0 ) }, // edge near y-plane 1857 { tcu::Vec3( 1, 1, 0.01f), tcu::Vec3( 0.01f, -0.01f, 0), tcu::Vec3( 0, 0, 0.99f) }, // edge near z-plane 1858 }; 1859 1860 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(quads); ++ndx) 1861 addChild(new QuadFillTest(m_context, (std::string("quad_at_origin_") + de::toString(ndx)).c_str(), "polygon edge clipping", VIEWPORT_CENTER, quads[ndx].d1, quads[ndx].d2)); 1862 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(edgeQuads); ++ndx) 1863 addChild(new QuadFillTest(m_context, (std::string("quad_near_edge_") + de::toString(ndx)).c_str(), "polygon edge clipping", VIEWPORT_CENTER, edgeQuads[ndx].d1, edgeQuads[ndx].d2, edgeQuads[ndx].center)); 1864 1865 // Polyfan 1866 addChild(new TriangleFanFillTest(m_context, "poly_fan", "polygon edge clipping", VIEWPORT_CENTER)); 1867 } 1868 1869 class PolyVertexClipTestGroup : public TestCaseGroup 1870 { 1871 public: 1872 PolyVertexClipTestGroup (Context& context); 1873 1874 void init (void); 1875 }; 1876 1877 PolyVertexClipTestGroup::PolyVertexClipTestGroup (Context& context) 1878 : TestCaseGroup(context, "triangle_vertex", "Clip n vertices") 1879 { 1880 } 1881 1882 void PolyVertexClipTestGroup::init (void) 1883 { 1884 const float far = 30000.0f; 1885 const float farForThreeVertex = 20000.0f; // 3 vertex clipping tests use smaller triangles 1886 const tcu::IVec3 outside[] = 1887 { 1888 // outside one clipping plane 1889 tcu::IVec3(-1, 0, 0), 1890 tcu::IVec3( 1, 0, 0), 1891 tcu::IVec3( 0, 1, 0), 1892 tcu::IVec3( 0, -1, 0), 1893 tcu::IVec3( 0, 0, 1), 1894 tcu::IVec3( 0, 0, -1), 1895 1896 // outside two clipping planes 1897 tcu::IVec3(-1, -1, 0), 1898 tcu::IVec3( 1, -1, 0), 1899 tcu::IVec3( 1, 1, 0), 1900 tcu::IVec3(-1, 1, 0), 1901 1902 tcu::IVec3(-1, 0, -1), 1903 tcu::IVec3( 1, 0, -1), 1904 tcu::IVec3( 1, 0, 1), 1905 tcu::IVec3(-1, 0, 1), 1906 1907 tcu::IVec3( 0, -1, -1), 1908 tcu::IVec3( 0, 1, -1), 1909 tcu::IVec3( 0, 1, 1), 1910 tcu::IVec3( 0, -1, 1), 1911 1912 // outside three clipping planes 1913 tcu::IVec3(-1, -1, 1), 1914 tcu::IVec3( 1, -1, 1), 1915 tcu::IVec3( 1, 1, 1), 1916 tcu::IVec3(-1, 1, 1), 1917 1918 tcu::IVec3(-1, -1, -1), 1919 tcu::IVec3( 1, -1, -1), 1920 tcu::IVec3( 1, 1, -1), 1921 tcu::IVec3(-1, 1, -1), 1922 }; 1923 1924 de::Random rnd(0xabcdef); 1925 1926 TestCaseGroup* clipOne = new TestCaseGroup(m_context, "clip_one", "Clip one vertex"); 1927 TestCaseGroup* clipTwo = new TestCaseGroup(m_context, "clip_two", "Clip two vertices"); 1928 TestCaseGroup* clipThree = new TestCaseGroup(m_context, "clip_three", "Clip three vertices"); 1929 1930 addChild(clipOne); 1931 addChild(clipTwo); 1932 addChild(clipThree); 1933 1934 // Test 1 point clipped 1935 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(outside); ++ndx) 1936 { 1937 const float w0 = rnd.getFloat(0.2f, 16.0f); 1938 const float w1 = rnd.getFloat(0.2f, 16.0f); 1939 const float w2 = rnd.getFloat(0.2f, 16.0f); 1940 const tcu::Vec4 white = tcu::Vec4( 1, 1, 1, 1); 1941 const tcu::Vec3 r0 = tcu::Vec3( 0.2f, 0.3f, 0); 1942 const tcu::Vec3 r1 = tcu::Vec3(-0.3f, -0.4f, 0); 1943 const tcu::Vec3 r2 = IVec3ToVec3(outside[ndx]) * far; 1944 const tcu::Vec4 p0 = tcu::Vec4(r0.x() * w0, r0.y() * w0, r0.z() * w0, w0); 1945 const tcu::Vec4 p1 = tcu::Vec4(r1.x() * w1, r1.y() * w1, r1.z() * w1, w1); 1946 const tcu::Vec4 p2 = tcu::Vec4(r2.x() * w2, r2.y() * w2, r2.z() * w2, w2); 1947 1948 const std::string name = std::string("clip") + 1949 (outside[ndx].x() > 0 ? "_pos_x" : (outside[ndx].x() < 0 ? "_neg_x" : "")) + 1950 (outside[ndx].y() > 0 ? "_pos_y" : (outside[ndx].y() < 0 ? "_neg_y" : "")) + 1951 (outside[ndx].z() > 0 ? "_pos_z" : (outside[ndx].z() < 0 ? "_neg_z" : "")); 1952 1953 const TriangleCase::TriangleData triangle = {p0, white, p1, white, p2, white}; 1954 1955 // don't try to test with degenerate (or almost degenerate) triangles 1956 if (outside[ndx].x() == 0 && outside[ndx].y() == 0) 1957 continue; 1958 1959 clipOne->addChild(new TriangleCase(m_context, name.c_str(), "clip one vertex", &triangle, &triangle + 1, VIEWPORT_CENTER)); 1960 } 1961 1962 // Special triangles for "clip_z" cases, default triangles is not good, since it has very small visible area => problems with MSAA 1963 { 1964 const tcu::Vec4 white = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 1965 1966 const TriangleCase::TriangleData posZTriangle = 1967 { 1968 tcu::Vec4( 0.0f, -0.7f, -0.9f, 1.0f), white, 1969 tcu::Vec4( 0.8f, 0.0f, -0.7f, 1.0f), white, 1970 tcu::Vec4(-0.9f, 0.9f, 3.0f, 1.0f), white 1971 }; 1972 const TriangleCase::TriangleData negZTriangle = 1973 { 1974 tcu::Vec4( 0.0f, -0.7f, 0.9f, 1.0f), white, 1975 tcu::Vec4( 0.4f, 0.0f, 0.7f, 1.0f), white, 1976 tcu::Vec4(-0.9f, 0.9f, -3.0f, 1.0f), white 1977 }; 1978 1979 clipOne->addChild(new TriangleCase(m_context, "clip_pos_z", "clip one vertex", &posZTriangle, &posZTriangle + 1, VIEWPORT_CENTER)); 1980 clipOne->addChild(new TriangleCase(m_context, "clip_neg_z", "clip one vertex", &negZTriangle, &negZTriangle + 1, VIEWPORT_CENTER)); 1981 } 1982 1983 // Test 2 points clipped 1984 for (int ndx1 = 0; ndx1 < DE_LENGTH_OF_ARRAY(outside); ++ndx1) 1985 for (int ndx2 = ndx1 + 1; ndx2 < DE_LENGTH_OF_ARRAY(outside); ++ndx2) 1986 { 1987 const float w0 = rnd.getFloat(0.2f, 16.0f); 1988 const float w1 = rnd.getFloat(0.2f, 16.0f); 1989 const float w2 = rnd.getFloat(0.2f, 16.0f); 1990 const tcu::Vec4 white = tcu::Vec4( 1, 1, 1, 1); 1991 const tcu::Vec3 r0 = tcu::Vec3( 0.2f, 0.3f, 0); 1992 const tcu::IVec3 r1 = outside[ndx1]; 1993 const tcu::IVec3 r2 = outside[ndx2]; 1994 const tcu::Vec4 p0 = tcu::Vec4(r0.x() * w0, r0.y() * w0, r0.z() * w0, w0); 1995 const tcu::Vec4 p1 = tcu::Vec4(float(r1.x()) * far * w1, float(r1.y()) * far * w1, float(r1.z()) * far * w1, w1); 1996 const tcu::Vec4 p2 = tcu::Vec4(float(r2.x()) * far * w2, float(r2.y()) * far * w2, float(r2.z()) * far * w2, w2); 1997 1998 const std::string name = std::string("clip") + 1999 (outside[ndx1].x() > 0 ? "_pos_x" : (outside[ndx1].x() < 0 ? "_neg_x" : "")) + 2000 (outside[ndx1].y() > 0 ? "_pos_y" : (outside[ndx1].y() < 0 ? "_neg_y" : "")) + 2001 (outside[ndx1].z() > 0 ? "_pos_z" : (outside[ndx1].z() < 0 ? "_neg_z" : "")) + 2002 "_and" + 2003 (outside[ndx2].x() > 0 ? "_pos_x" : (outside[ndx2].x() < 0 ? "_neg_x" : "")) + 2004 (outside[ndx2].y() > 0 ? "_pos_y" : (outside[ndx2].y() < 0 ? "_neg_y" : "")) + 2005 (outside[ndx2].z() > 0 ? "_pos_z" : (outside[ndx2].z() < 0 ? "_neg_z" : "")); 2006 2007 const TriangleCase::TriangleData triangle = {p0, white, p1, white, p2, white}; 2008 2009 if (twoPointClippedTriangleInvisible(r0, r1, r2)) 2010 continue; 2011 2012 clipTwo->addChild(new TriangleCase(m_context, name.c_str(), "clip two vertices", &triangle, &triangle + 1, VIEWPORT_CENTER)); 2013 } 2014 2015 // Test 3 points clipped 2016 for (int ndx1 = 0; ndx1 < DE_LENGTH_OF_ARRAY(outside); ++ndx1) 2017 for (int ndx2 = ndx1 + 1; ndx2 < DE_LENGTH_OF_ARRAY(outside); ++ndx2) 2018 for (int ndx3 = ndx2 + 1; ndx3 < DE_LENGTH_OF_ARRAY(outside); ++ndx3) 2019 { 2020 const float w0 = rnd.getFloat(0.2f, 16.0f); 2021 const float w1 = rnd.getFloat(0.2f, 16.0f); 2022 const float w2 = rnd.getFloat(0.2f, 16.0f); 2023 const tcu::Vec4 white = tcu::Vec4(1, 1, 1, 1); 2024 const tcu::IVec3 r0 = outside[ndx1]; 2025 const tcu::IVec3 r1 = outside[ndx2]; 2026 const tcu::IVec3 r2 = outside[ndx3]; 2027 const tcu::Vec4 p0 = tcu::Vec4(float(r0.x()) * farForThreeVertex * w0, float(r0.y()) * farForThreeVertex * w0, float(r0.z()) * farForThreeVertex * w0, w0); 2028 const tcu::Vec4 p1 = tcu::Vec4(float(r1.x()) * farForThreeVertex * w1, float(r1.y()) * farForThreeVertex * w1, float(r1.z()) * farForThreeVertex * w1, w1); 2029 const tcu::Vec4 p2 = tcu::Vec4(float(r2.x()) * farForThreeVertex * w2, float(r2.y()) * farForThreeVertex * w2, float(r2.z()) * farForThreeVertex * w2, w2); 2030 2031 // ignore cases where polygon is along xz or yz planes 2032 if (pointsOnLine(r0.swizzle(0, 1), r1.swizzle(0, 1), r2.swizzle(0, 1))) 2033 continue; 2034 2035 // triangle is visible only if it intersects the origin 2036 if (pointOnTriangle(tcu::IVec3(0, 0, 0), r0, r1, r2)) 2037 { 2038 const TriangleCase::TriangleData triangle = {p0, white, p1, white, p2, white}; 2039 const std::string name = std::string("clip") + 2040 (outside[ndx1].x() > 0 ? "_pos_x" : (outside[ndx1].x() < 0 ? "_neg_x" : "")) + 2041 (outside[ndx1].y() > 0 ? "_pos_y" : (outside[ndx1].y() < 0 ? "_neg_y" : "")) + 2042 (outside[ndx1].z() > 0 ? "_pos_z" : (outside[ndx1].z() < 0 ? "_neg_z" : "")) + 2043 "_and" + 2044 (outside[ndx2].x() > 0 ? "_pos_x" : (outside[ndx2].x() < 0 ? "_neg_x" : "")) + 2045 (outside[ndx2].y() > 0 ? "_pos_y" : (outside[ndx2].y() < 0 ? "_neg_y" : "")) + 2046 (outside[ndx2].z() > 0 ? "_pos_z" : (outside[ndx2].z() < 0 ? "_neg_z" : "")) + 2047 "_and" + 2048 (outside[ndx3].x() > 0 ? "_pos_x" : (outside[ndx3].x() < 0 ? "_neg_x" : "")) + 2049 (outside[ndx3].y() > 0 ? "_pos_y" : (outside[ndx3].y() < 0 ? "_neg_y" : "")) + 2050 (outside[ndx3].z() > 0 ? "_pos_z" : (outside[ndx3].z() < 0 ? "_neg_z" : "")); 2051 2052 clipThree->addChild(new TriangleCase(m_context, name.c_str(), "clip three vertices", &triangle, &triangle + 1, VIEWPORT_CENTER)); 2053 } 2054 } 2055 } 2056 2057 } // anonymous 2058 2059 ClippingTests::ClippingTests (Context& context) 2060 : TestCaseGroup(context, "clipping", "Clipping tests") 2061 { 2062 } 2063 2064 ClippingTests::~ClippingTests (void) 2065 { 2066 } 2067 2068 void ClippingTests::init (void) 2069 { 2070 addChild(new PointsTestGroup (m_context)); 2071 addChild(new LinesTestGroup (m_context)); 2072 addChild(new PolysTestGroup (m_context)); 2073 addChild(new PolyEdgesTestGroup (m_context)); 2074 addChild(new PolyVertexClipTestGroup(m_context)); 2075 } 2076 2077 } // Functional 2078 } // gles2 2079 } // deqp 2080