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