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