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