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