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