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