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