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