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