• 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 Functional rasterization tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fRasterizationTests.hpp"
25 #include "glsRasterizationTestUtil.hpp"
26 #include "tcuSurface.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "tcuStringTemplate.hpp"
30 #include "gluShaderProgram.hpp"
31 #include "gluRenderContext.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluStrUtil.hpp"
34 #include "deStringUtil.hpp"
35 #include "deRandom.hpp"
36 #include "glwFunctions.hpp"
37 #include "glwEnums.hpp"
38 
39 #include <vector>
40 
41 namespace deqp
42 {
43 namespace gles2
44 {
45 namespace Functional
46 {
47 namespace
48 {
49 
50 using namespace gls::RasterizationTestUtil;
51 
52 static const char* const s_shaderVertexTemplate =	"attribute highp vec4 a_position;\n"
53 													"attribute highp vec4 a_color;\n"
54 													"varying highp vec4 v_color;\n"
55 													"uniform highp float u_pointSize;\n"
56 													"void main ()\n"
57 													"{\n"
58 													"	gl_Position = a_position;\n"
59 													"	gl_PointSize = u_pointSize;\n"
60 													"	v_color = a_color;\n"
61 													"}\n";
62 static const char* const s_shaderFragmentTemplate =	"varying mediump vec4 v_color;\n"
63 													"void main ()\n"
64 													"{\n"
65 													"	gl_FragColor = v_color;\n"
66 													"}\n";
67 enum InterpolationCaseFlags
68 {
69 	INTERPOLATIONFLAGS_NONE = 0,
70 	INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
71 };
72 
73 enum PrimitiveWideness
74 {
75 	PRIMITIVEWIDENESS_NARROW = 0,
76 	PRIMITIVEWIDENESS_WIDE,
77 
78 	PRIMITIVEWIDENESS_LAST
79 };
80 
81 class BaseRenderingCase : public TestCase
82 {
83 public:
84 							BaseRenderingCase	(Context& context, const char* name, const char* desc, int renderSize = 256);
85 							~BaseRenderingCase	(void);
86 	virtual void			init				(void);
87 	void					deinit				(void);
88 
89 protected:
90 	void					drawPrimitives		(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType);
91 	void					drawPrimitives		(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, glw::GLenum primitiveType);
92 
93 	const int				m_renderSize;
94 	int						m_numSamples;
95 	int						m_subpixelBits;
96 	float					m_pointSize;
97 	float					m_lineWidth;
98 
99 private:
100 	glu::ShaderProgram*		m_shader;
101 };
102 
BaseRenderingCase(Context & context,const char * name,const char * desc,int renderSize)103 BaseRenderingCase::BaseRenderingCase (Context& context, const char* name, const char* desc, int renderSize)
104 	: TestCase				(context, name, desc)
105 	, m_renderSize			(renderSize)
106 	, m_numSamples			(-1)
107 	, m_subpixelBits		(-1)
108 	, m_pointSize			(1.0f)
109 	, m_lineWidth			(1.0f)
110 	, m_shader				(DE_NULL)
111 {
112 }
113 
~BaseRenderingCase(void)114 BaseRenderingCase::~BaseRenderingCase (void)
115 {
116 	deinit();
117 }
118 
init(void)119 void BaseRenderingCase::init (void)
120 {
121 	const int width	 = m_context.getRenderTarget().getWidth();
122 	const int height = m_context.getRenderTarget().getHeight();
123 
124 	// Requirements
125 
126 	if (width < m_renderSize || height < m_renderSize)
127 		throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_renderSize) + "x" + de::toString(m_renderSize));
128 
129 	if (m_lineWidth != 1.0f)
130 	{
131 		float range[2] = { 0.0f, 0.0f };
132 		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
133 
134 		if (m_lineWidth < range[0] || m_lineWidth > range[1])
135 			throw tcu::NotSupportedError(std::string("Support for line width ") + de::toString(m_lineWidth) + " is required.");
136 
137 		m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
138 	}
139 
140 	if (m_pointSize != 1.0f)
141 	{
142 		float range[2] = { 0.0f, 0.0f };
143 		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
144 
145 		if (m_pointSize < range[0] || m_pointSize > range[1])
146 			throw tcu::NotSupportedError(std::string("Support for point size ") + de::toString(m_pointSize) + " is required.");
147 
148 		m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
149 	}
150 
151 	// Query info
152 
153 	m_numSamples = m_context.getRenderTarget().getNumSamples();
154 	m_context.getRenderContext().getFunctions().getIntegerv(GL_SUBPIXEL_BITS, &m_subpixelBits);
155 
156 	m_testCtx.getLog() << tcu::TestLog::Message << "Sample count = " << m_numSamples << tcu::TestLog::EndMessage;
157 	m_testCtx.getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
158 
159 	// Gen shader
160 
161 	{
162 		tcu::StringTemplate					vertexSource	(s_shaderVertexTemplate);
163 		tcu::StringTemplate					fragmentSource	(s_shaderFragmentTemplate);
164 		std::map<std::string, std::string>	params;
165 
166 		m_shader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource.specialize(params)) << glu::FragmentSource(fragmentSource.specialize(params)));
167 		if (!m_shader->isOk())
168 			throw tcu::TestError("could not create shader");
169 	}
170 }
171 
deinit(void)172 void BaseRenderingCase::deinit (void)
173 {
174 	if (m_shader)
175 	{
176 		delete m_shader;
177 		m_shader = DE_NULL;
178 	}
179 }
180 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,glw::GLenum primitiveType)181 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType)
182 {
183 	// default to color white
184 	const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
185 
186 	drawPrimitives(result, vertexData, colorData, primitiveType);
187 }
188 
drawPrimitives(tcu::Surface & result,const std::vector<tcu::Vec4> & vertexData,const std::vector<tcu::Vec4> & colorData,glw::GLenum primitiveType)189 void BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& colorData, glw::GLenum primitiveType)
190 {
191 	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
192 	const glw::GLint		positionLoc		= gl.getAttribLocation(m_shader->getProgram(), "a_position");
193 	const glw::GLint		colorLoc		= gl.getAttribLocation(m_shader->getProgram(), "a_color");
194 	const glw::GLint		pointSizeLoc	= gl.getUniformLocation(m_shader->getProgram(), "u_pointSize");
195 
196 	gl.clearColor					(0, 0, 0, 1);
197 	gl.clear						(GL_COLOR_BUFFER_BIT);
198 	gl.viewport						(0, 0, m_renderSize, m_renderSize);
199 	gl.useProgram					(m_shader->getProgram());
200 	gl.enableVertexAttribArray		(positionLoc);
201 	gl.vertexAttribPointer			(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertexData[0]);
202 	gl.enableVertexAttribArray		(colorLoc);
203 	gl.vertexAttribPointer			(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, &colorData[0]);
204 	gl.uniform1f					(pointSizeLoc, m_pointSize);
205 	gl.lineWidth					(m_lineWidth);
206 	gl.drawArrays					(primitiveType, 0, (glw::GLsizei)vertexData.size());
207 	gl.disableVertexAttribArray		(colorLoc);
208 	gl.disableVertexAttribArray		(positionLoc);
209 	gl.useProgram					(0);
210 	gl.finish						();
211 	GLU_EXPECT_NO_ERROR				(gl.getError(), "draw primitives");
212 
213 	glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
214 }
215 
216 class BaseTriangleCase : public BaseRenderingCase
217 {
218 public:
219 							BaseTriangleCase	(Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType);
220 							~BaseTriangleCase	(void);
221 	IterateResult			iterate				(void);
222 
223 private:
224 	virtual void			generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
225 
226 	int						m_iteration;
227 	const int				m_iterationCount;
228 	const glw::GLenum		m_primitiveDrawType;
229 	bool					m_allIterationsPassed;
230 };
231 
BaseTriangleCase(Context & context,const char * name,const char * desc,glw::GLenum primitiveDrawType)232 BaseTriangleCase::BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType)
233 	: BaseRenderingCase		(context, name, desc)
234 	, m_iteration			(0)
235 	, m_iterationCount		(3)
236 	, m_primitiveDrawType	(primitiveDrawType)
237 	, m_allIterationsPassed	(true)
238 {
239 }
240 
~BaseTriangleCase(void)241 BaseTriangleCase::~BaseTriangleCase (void)
242 {
243 }
244 
iterate(void)245 BaseTriangleCase::IterateResult BaseTriangleCase::iterate (void)
246 {
247 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
248 	const tcu::ScopedLogSection						section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
249 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
250 	std::vector<tcu::Vec4>							drawBuffer;
251 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
252 
253 	generateTriangles(m_iteration, drawBuffer, triangles);
254 
255 	// draw image
256 	drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
257 
258 	// compare
259 	{
260 		bool					compareOk;
261 		RasterizationArguments	args;
262 		TriangleSceneSpec		scene;
263 
264 		args.numSamples		= m_numSamples;
265 		args.subpixelBits	= m_subpixelBits;
266 		args.redBits		= m_context.getRenderTarget().getPixelFormat().redBits;
267 		args.greenBits		= m_context.getRenderTarget().getPixelFormat().greenBits;
268 		args.blueBits		= m_context.getRenderTarget().getPixelFormat().blueBits;
269 
270 		scene.triangles.swap(triangles);
271 
272 		compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
273 
274 		if (!compareOk)
275 			m_allIterationsPassed = false;
276 	}
277 
278 	// result
279 	if (++m_iteration == m_iterationCount)
280 	{
281 		if (m_allIterationsPassed)
282 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
283 		else
284 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
285 
286 		return STOP;
287 	}
288 	else
289 		return CONTINUE;
290 }
291 
292 class BaseLineCase : public BaseRenderingCase
293 {
294 public:
295 							BaseLineCase		(Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness);
296 							~BaseLineCase		(void);
297 	IterateResult			iterate				(void);
298 
299 private:
300 	virtual void			generateLines		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
301 
302 	int						m_iteration;
303 	const int				m_iterationCount;
304 	const glw::GLenum		m_primitiveDrawType;
305 	const PrimitiveWideness	m_primitiveWideness;
306 	bool					m_allIterationsPassed;
307 
308 	static const float		s_wideSize;
309 };
310 
311 const float BaseLineCase::s_wideSize = 5.0f;
312 
BaseLineCase(Context & context,const char * name,const char * desc,glw::GLenum primitiveDrawType,PrimitiveWideness wideness)313 BaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness)
314 	: BaseRenderingCase		(context, name, desc)
315 	, m_iteration			(0)
316 	, m_iterationCount		(3)
317 	, m_primitiveDrawType	(primitiveDrawType)
318 	, m_primitiveWideness	(wideness)
319 	, m_allIterationsPassed	(true)
320 {
321 	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
322 	m_lineWidth = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
323 }
324 
~BaseLineCase(void)325 BaseLineCase::~BaseLineCase (void)
326 {
327 }
328 
iterate(void)329 BaseLineCase::IterateResult BaseLineCase::iterate (void)
330 {
331 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
332 	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
333 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
334 	std::vector<tcu::Vec4>					drawBuffer;
335 	std::vector<LineSceneSpec::SceneLine>	lines;
336 
337 	// last iteration, max out size
338 	if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE &&
339 		m_iteration+1 == m_iterationCount)
340 	{
341 		float range[2] = { 0.0f, 0.0f };
342 		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
343 
344 		m_lineWidth = range[1];
345 	}
346 
347 	// gen data
348 	generateLines(m_iteration, drawBuffer, lines);
349 
350 	// draw image
351 	drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
352 
353 	// compare
354 	{
355 		bool					compareOk;
356 		RasterizationArguments	args;
357 		LineSceneSpec			scene;
358 
359 		args.numSamples		= m_numSamples;
360 		args.subpixelBits	= m_subpixelBits;
361 		args.redBits		= m_context.getRenderTarget().getPixelFormat().redBits;
362 		args.greenBits		= m_context.getRenderTarget().getPixelFormat().greenBits;
363 		args.blueBits		= m_context.getRenderTarget().getPixelFormat().blueBits;
364 
365 		scene.lines.swap(lines);
366 		scene.lineWidth = m_lineWidth;
367 
368 		compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
369 
370 		if (!compareOk)
371 			m_allIterationsPassed = false;
372 	}
373 
374 	// result
375 	if (++m_iteration == m_iterationCount)
376 	{
377 		if (m_allIterationsPassed)
378 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
379 		else
380 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
381 
382 		return STOP;
383 	}
384 	else
385 		return CONTINUE;
386 }
387 
388 class PointCase : public BaseRenderingCase
389 {
390 public:
391 							PointCase		(Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
392 							~PointCase		(void);
393 	IterateResult			iterate			(void);
394 
395 private:
396 	void					generatePoints	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
397 
398 	int						m_iteration;
399 	const int				m_iterationCount;
400 	const PrimitiveWideness	m_primitiveWideness;
401 	bool					m_allIterationsPassed;
402 
403 	static const float		s_wideSize;
404 };
405 
406 const float PointCase::s_wideSize = 10.0f;
407 
PointCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)408 PointCase::PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
409 	: BaseRenderingCase		(context, name, desc)
410 	, m_iteration			(0)
411 	, m_iterationCount		(3)
412 	, m_primitiveWideness	(wideness)
413 	, m_allIterationsPassed	(true)
414 {
415 	m_pointSize = (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE) ? (s_wideSize) : (1.0f);
416 }
417 
~PointCase(void)418 PointCase::~PointCase (void)
419 {
420 }
421 
iterate(void)422 PointCase::IterateResult PointCase::iterate (void)
423 {
424 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
425 	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
426 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
427 	std::vector<tcu::Vec4>					drawBuffer;
428 	std::vector<PointSceneSpec::ScenePoint>	points;
429 
430 	// last iteration, max out size
431 	if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE &&
432 		m_iteration+1 == m_iterationCount)
433 	{
434 		float range[2] = { 0.0f, 0.0f };
435 		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
436 
437 		m_pointSize = range[1];
438 	}
439 
440 	// gen data
441 	generatePoints(m_iteration, drawBuffer, points);
442 
443 	// draw image
444 	drawPrimitives(resultImage, drawBuffer, GL_POINTS);
445 
446 	// compare
447 	{
448 		bool					compareOk;
449 		RasterizationArguments	args;
450 		PointSceneSpec			scene;
451 
452 		args.numSamples		= m_numSamples;
453 		args.subpixelBits	= m_subpixelBits;
454 		args.redBits		= m_context.getRenderTarget().getPixelFormat().redBits;
455 		args.greenBits		= m_context.getRenderTarget().getPixelFormat().greenBits;
456 		args.blueBits		= m_context.getRenderTarget().getPixelFormat().blueBits;
457 
458 		scene.points.swap(points);
459 
460 		compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
461 
462 		if (!compareOk)
463 			m_allIterationsPassed = false;
464 	}
465 
466 	// result
467 	if (++m_iteration == m_iterationCount)
468 	{
469 		if (m_allIterationsPassed)
470 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
471 		else
472 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
473 
474 		return STOP;
475 	}
476 	else
477 		return CONTINUE;
478 }
479 
generatePoints(int iteration,std::vector<tcu::Vec4> & outData,std::vector<PointSceneSpec::ScenePoint> & outPoints)480 void PointCase::generatePoints	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
481 {
482 	outData.resize(6);
483 
484 	switch (iteration)
485 	{
486 		case 0:
487 			// \note: these values are chosen arbitrarily
488 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
489 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
490 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
491 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
492 			outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
493 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
494 			break;
495 
496 		case 1:
497 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
498 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
499 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
500 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
501 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
502 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
503 			break;
504 
505 		case 2:
506 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
507 			outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
508 			outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
509 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
510 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
511 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
512 			break;
513 	}
514 
515 	outPoints.resize(outData.size());
516 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
517 	{
518 		outPoints[pointNdx].position = outData[pointNdx];
519 		outPoints[pointNdx].pointSize = m_pointSize;
520 	}
521 
522 	// log
523 	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << m_pointSize << ")" << tcu::TestLog::EndMessage;
524 	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
525 		m_testCtx.getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
526 }
527 
528 class TrianglesCase : public BaseTriangleCase
529 {
530 public:
531 			TrianglesCase		(Context& context, const char* name, const char* desc);
532 			~TrianglesCase		(void);
533 
534 	void	generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
535 };
536 
TrianglesCase(Context & context,const char * name,const char * desc)537 TrianglesCase::TrianglesCase (Context& context, const char* name, const char* desc)
538 	: BaseTriangleCase(context, name, desc, GL_TRIANGLES)
539 {
540 }
541 
~TrianglesCase(void)542 TrianglesCase::~TrianglesCase (void)
543 {
544 
545 }
546 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)547 void TrianglesCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
548 {
549 	outData.resize(6);
550 
551 	switch (iteration)
552 	{
553 		case 0:
554 			// \note: these values are chosen arbitrarily
555 			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
556 			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
557 			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
558 			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
559 			outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
560 			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
561 			break;
562 
563 		case 1:
564 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
565 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
566 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
567 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
568 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
569 			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
570 			break;
571 
572 		case 2:
573 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
574 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
575 			outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
576 			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
577 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
578 			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
579 			break;
580 	}
581 
582 	outTriangles.resize(2);
583 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
584 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
585 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
586 
587 	outTriangles[1].positions[0] = outData[3];	outTriangles[1].sharedEdge[0] = false;
588 	outTriangles[1].positions[1] = outData[4];	outTriangles[1].sharedEdge[1] = false;
589 	outTriangles[1].positions[2] = outData[5];	outTriangles[1].sharedEdge[2] = false;
590 
591 	// log
592 	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
593 	for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
594 	{
595 		m_testCtx.getLog()
596 			<< tcu::TestLog::Message
597 			<< "Triangle " << (triangleNdx+1) << ":"
598 			<< "\n\t" << outTriangles[triangleNdx].positions[0]
599 			<< "\n\t" << outTriangles[triangleNdx].positions[1]
600 			<< "\n\t" << outTriangles[triangleNdx].positions[2]
601 			<< tcu::TestLog::EndMessage;
602 	}
603 }
604 
605 class TriangleStripCase : public BaseTriangleCase
606 {
607 public:
608 			TriangleStripCase	(Context& context, const char* name, const char* desc);
609 
610 	void	generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
611 };
612 
TriangleStripCase(Context & context,const char * name,const char * desc)613 TriangleStripCase::TriangleStripCase (Context& context, const char* name, const char* desc)
614 	: BaseTriangleCase(context, name, desc, GL_TRIANGLE_STRIP)
615 {
616 }
617 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)618 void TriangleStripCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
619 {
620 	outData.resize(5);
621 
622 	switch (iteration)
623 	{
624 		case 0:
625 			// \note: these values are chosen arbitrarily
626 			outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
627 			outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
628 			outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
629 			outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
630 			outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
631 			break;
632 
633 		case 1:
634 			outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
635 			outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
636 			outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
637 			outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
638 			outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
639 			break;
640 
641 		case 2:
642 			outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
643 			outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
644 			outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
645 			outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
646 			outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
647 			break;
648 	}
649 
650 	outTriangles.resize(3);
651 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
652 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = true;
653 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
654 
655 	outTriangles[1].positions[0] = outData[2];	outTriangles[1].sharedEdge[0] = true;
656 	outTriangles[1].positions[1] = outData[1];	outTriangles[1].sharedEdge[1] = false;
657 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
658 
659 	outTriangles[2].positions[0] = outData[2];	outTriangles[2].sharedEdge[0] = true;
660 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
661 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
662 
663 	// log
664 	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
665 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
666 	{
667 		m_testCtx.getLog()
668 			<< tcu::TestLog::Message
669 			<< "\t" << outData[vtxNdx]
670 			<< tcu::TestLog::EndMessage;
671 	}
672 }
673 
674 class TriangleFanCase : public BaseTriangleCase
675 {
676 public:
677 			TriangleFanCase		(Context& context, const char* name, const char* desc);
678 
679 	void	generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
680 };
681 
TriangleFanCase(Context & context,const char * name,const char * desc)682 TriangleFanCase::TriangleFanCase (Context& context, const char* name, const char* desc)
683 	: BaseTriangleCase(context, name, desc, GL_TRIANGLE_FAN)
684 {
685 }
686 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData,std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles)687 void TriangleFanCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
688 {
689 	outData.resize(5);
690 
691 	switch (iteration)
692 	{
693 		case 0:
694 			// \note: these values are chosen arbitrarily
695 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
696 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
697 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
698 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
699 			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
700 			break;
701 
702 		case 1:
703 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
704 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
705 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
706 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
707 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
708 			break;
709 
710 		case 2:
711 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
712 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
713 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
714 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
715 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
716 			break;
717 	}
718 
719 	outTriangles.resize(3);
720 	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
721 	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
722 	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = true;
723 
724 	outTriangles[1].positions[0] = outData[0];	outTriangles[1].sharedEdge[0] = true;
725 	outTriangles[1].positions[1] = outData[2];	outTriangles[1].sharedEdge[1] = false;
726 	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
727 
728 	outTriangles[2].positions[0] = outData[0];	outTriangles[2].sharedEdge[0] = true;
729 	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
730 	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
731 
732 	// log
733 	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
734 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
735 	{
736 		m_testCtx.getLog()
737 			<< tcu::TestLog::Message
738 			<< "\t" << outData[vtxNdx]
739 			<< tcu::TestLog::EndMessage;
740 	}
741 }
742 
743 class LinesCase : public BaseLineCase
744 {
745 public:
746 			LinesCase		(Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
747 
748 	void	generateLines	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
749 };
750 
LinesCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)751 LinesCase::LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
752 	: BaseLineCase(context, name, desc, GL_LINES, wideness)
753 {
754 }
755 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)756 void LinesCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
757 {
758 	outData.resize(6);
759 
760 	switch (iteration)
761 	{
762 		case 0:
763 			// \note: these values are chosen arbitrarily
764 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
765 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
766 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
767 			outData[3] = tcu::Vec4(-0.3f,   0.2f, 0.0f, 1.0f);
768 			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
769 			outData[5] = tcu::Vec4( 0.1f,   0.5f, 0.0f, 1.0f);
770 			break;
771 
772 		case 1:
773 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
774 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
775 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
776 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
777 			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
778 			outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
779 			break;
780 
781 		case 2:
782 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
783 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
784 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
785 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
786 			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
787 			outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
788 			break;
789 	}
790 
791 	outLines.resize(3);
792 	outLines[0].positions[0] = outData[0];
793 	outLines[0].positions[1] = outData[1];
794 	outLines[1].positions[0] = outData[2];
795 	outLines[1].positions[1] = outData[3];
796 	outLines[2].positions[0] = outData[4];
797 	outLines[2].positions[1] = outData[5];
798 
799 	// log
800 	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << m_lineWidth << ")" << tcu::TestLog::EndMessage;
801 	for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
802 	{
803 		m_testCtx.getLog()
804 			<< tcu::TestLog::Message
805 			<< "Line " << (lineNdx+1) << ":"
806 			<< "\n\t" << outLines[lineNdx].positions[0]
807 			<< "\n\t" << outLines[lineNdx].positions[1]
808 			<< tcu::TestLog::EndMessage;
809 	}
810 }
811 
812 class LineStripCase : public BaseLineCase
813 {
814 public:
815 			LineStripCase	(Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
816 
817 	void	generateLines	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
818 };
819 
LineStripCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)820 LineStripCase::LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
821 	: BaseLineCase(context, name, desc, GL_LINE_STRIP, wideness)
822 {
823 }
824 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)825 void LineStripCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
826 {
827 	outData.resize(4);
828 
829 	switch (iteration)
830 	{
831 		case 0:
832 			// \note: these values are chosen arbitrarily
833 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
834 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
835 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
836 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
837 			break;
838 
839 		case 1:
840 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
841 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
842 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
843 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
844 			break;
845 
846 		case 2:
847 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
848 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
849 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
850 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
851 			break;
852 	}
853 
854 	outLines.resize(3);
855 	outLines[0].positions[0] = outData[0];
856 	outLines[0].positions[1] = outData[1];
857 	outLines[1].positions[0] = outData[1];
858 	outLines[1].positions[1] = outData[2];
859 	outLines[2].positions[0] = outData[2];
860 	outLines[2].positions[1] = outData[3];
861 
862 	// log
863 	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
864 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
865 	{
866 		m_testCtx.getLog()
867 			<< tcu::TestLog::Message
868 			<< "\t" << outData[vtxNdx]
869 			<< tcu::TestLog::EndMessage;
870 	}
871 }
872 
873 class LineLoopCase : public BaseLineCase
874 {
875 public:
876 			LineLoopCase	(Context& context, const char* name, const char* desc, PrimitiveWideness wideness);
877 
878 	void	generateLines	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
879 };
880 
LineLoopCase(Context & context,const char * name,const char * desc,PrimitiveWideness wideness)881 LineLoopCase::LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness)
882 	: BaseLineCase(context, name, desc, GL_LINE_LOOP, wideness)
883 {
884 }
885 
generateLines(int iteration,std::vector<tcu::Vec4> & outData,std::vector<LineSceneSpec::SceneLine> & outLines)886 void LineLoopCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
887 {
888 	outData.resize(4);
889 
890 	switch (iteration)
891 	{
892 		case 0:
893 			// \note: these values are chosen arbitrarily
894 			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
895 			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
896 			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
897 			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
898 			break;
899 
900 		case 1:
901 			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
902 			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
903 			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
904 			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
905 			break;
906 
907 		case 2:
908 			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
909 			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
910 			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
911 			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
912 			break;
913 	}
914 
915 	outLines.resize(4);
916 	outLines[0].positions[0] = outData[0];
917 	outLines[0].positions[1] = outData[1];
918 	outLines[1].positions[0] = outData[1];
919 	outLines[1].positions[1] = outData[2];
920 	outLines[2].positions[0] = outData[2];
921 	outLines[2].positions[1] = outData[3];
922 	outLines[3].positions[0] = outData[3];
923 	outLines[3].positions[1] = outData[0];
924 
925 	// log
926 	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line loop, width = " << m_lineWidth << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
927 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
928 	{
929 		m_testCtx.getLog()
930 			<< tcu::TestLog::Message
931 			<< "\t" << outData[vtxNdx]
932 			<< tcu::TestLog::EndMessage;
933 	}
934 }
935 
936 class FillRuleCase : public BaseRenderingCase
937 {
938 public:
939 	enum FillRuleCaseType
940 	{
941 		FILLRULECASE_BASIC = 0,
942 		FILLRULECASE_REVERSED,
943 		FILLRULECASE_CLIPPED_FULL,
944 		FILLRULECASE_CLIPPED_PARTIAL,
945 		FILLRULECASE_PROJECTED,
946 
947 		FILLRULECASE_LAST
948 	};
949 
950 							FillRuleCase		(Context& ctx, const char* name, const char* desc, FillRuleCaseType type);
951 							~FillRuleCase		(void);
952 	IterateResult			iterate				(void);
953 
954 private:
955 	int						getRenderSize		(FillRuleCase::FillRuleCaseType type) const;
956 	int						getNumIterations	(FillRuleCase::FillRuleCaseType type) const;
957 	void					generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData) const;
958 
959 	const FillRuleCaseType	m_caseType;
960 	int						m_iteration;
961 	const int				m_iterationCount;
962 	bool					m_allIterationsPassed;
963 
964 };
965 
FillRuleCase(Context & ctx,const char * name,const char * desc,FillRuleCaseType type)966 FillRuleCase::FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type)
967 	: BaseRenderingCase		(ctx, name, desc, getRenderSize(type))
968 	, m_caseType			(type)
969 	, m_iteration			(0)
970 	, m_iterationCount		(getNumIterations(type))
971 	, m_allIterationsPassed	(true)
972 {
973 	DE_ASSERT(type < FILLRULECASE_LAST);
974 }
975 
~FillRuleCase(void)976 FillRuleCase::~FillRuleCase (void)
977 {
978 	deinit();
979 }
980 
iterate(void)981 FillRuleCase::IterateResult FillRuleCase::iterate (void)
982 {
983 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
984 	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
985 	const int								thresholdRed			= 1 << (8 - m_context.getRenderTarget().getPixelFormat().redBits);
986 	const int								thresholdGreen			= 1 << (8 - m_context.getRenderTarget().getPixelFormat().greenBits);
987 	const int								thresholdBlue			= 1 << (8 - m_context.getRenderTarget().getPixelFormat().blueBits);
988 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
989 	std::vector<tcu::Vec4>					drawBuffer;
990 	bool									imageShown				= false;
991 
992 	generateTriangles(m_iteration, drawBuffer);
993 
994 	// draw image
995 	{
996 		const glw::Functions&			gl				= m_context.getRenderContext().getFunctions();
997 		const std::vector<tcu::Vec4>	colorBuffer		(drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
998 
999 		m_testCtx.getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1000 
1001 		gl.enable(GL_BLEND);
1002 		gl.blendEquation(GL_FUNC_ADD);
1003 		gl.blendFunc(GL_ONE, GL_ONE);
1004 		drawPrimitives(resultImage, drawBuffer, colorBuffer, GL_TRIANGLES);
1005 	}
1006 
1007 	// verify no overdraw
1008 	{
1009 		const tcu::RGBA	triangleColor	= tcu::RGBA(127, 127, 127, 255);
1010 		bool			overdraw		= false;
1011 
1012 		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1013 
1014 		for (int y = 0; y < resultImage.getHeight(); ++y)
1015 		for (int x = 0; x < resultImage.getWidth();  ++x)
1016 		{
1017 			const tcu::RGBA color = resultImage.getPixel(x, y);
1018 
1019 			// color values are greater than triangle color? Allow lower values for multisampled edges and background.
1020 			if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
1021 				(color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1022 				(color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
1023 				overdraw = true;
1024 		}
1025 
1026 		// results
1027 		if (!overdraw)
1028 			m_testCtx.getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1029 		else
1030 		{
1031 			m_testCtx.getLog()	<< tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1032 			m_testCtx.getLog()	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1033 								<< tcu::TestLog::Image("Result", "Result", resultImage)
1034 								<< tcu::TestLog::EndImageSet;
1035 
1036 			imageShown = true;
1037 			m_allIterationsPassed = false;
1038 		}
1039 	}
1040 
1041 	// verify no missing fragments in the full viewport case
1042 	if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1043 	{
1044 		bool missingFragments = false;
1045 
1046 		m_testCtx.getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1047 
1048 		for (int y = 0; y < resultImage.getHeight(); ++y)
1049 		for (int x = 0; x < resultImage.getWidth();  ++x)
1050 		{
1051 			const tcu::RGBA color = resultImage.getPixel(x, y);
1052 
1053 			// black? (background)
1054 			if (color.getRed()   <= thresholdRed   ||
1055 				color.getGreen() <= thresholdGreen ||
1056 				color.getBlue()  <= thresholdBlue)
1057 				missingFragments = true;
1058 		}
1059 
1060 		// results
1061 		if (!missingFragments)
1062 			m_testCtx.getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1063 		else
1064 		{
1065 			m_testCtx.getLog()	<< tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1066 
1067 			if (!imageShown)
1068 			{
1069 				m_testCtx.getLog()	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1070 									<< tcu::TestLog::Image("Result", "Result", resultImage)
1071 									<< tcu::TestLog::EndImageSet;
1072 			}
1073 
1074 			m_allIterationsPassed = false;
1075 		}
1076 	}
1077 
1078 	// result
1079 	if (++m_iteration == m_iterationCount)
1080 	{
1081 		if (m_allIterationsPassed)
1082 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1083 		else
1084 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixels");
1085 
1086 		return STOP;
1087 	}
1088 	else
1089 		return CONTINUE;
1090 }
1091 
getRenderSize(FillRuleCase::FillRuleCaseType type) const1092 int FillRuleCase::getRenderSize (FillRuleCase::FillRuleCaseType type) const
1093 {
1094 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1095 		return 64;
1096 	else
1097 		return 256;
1098 }
1099 
getNumIterations(FillRuleCase::FillRuleCaseType type) const1100 int FillRuleCase::getNumIterations (FillRuleCase::FillRuleCaseType type) const
1101 {
1102 	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1103 		return 15;
1104 	else
1105 		return 2;
1106 }
1107 
generateTriangles(int iteration,std::vector<tcu::Vec4> & outData) const1108 void FillRuleCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1109 {
1110 	switch (m_caseType)
1111 	{
1112 		case FILLRULECASE_BASIC:
1113 		case FILLRULECASE_REVERSED:
1114 		case FILLRULECASE_PROJECTED:
1115 		{
1116 			const int	numRows		= 4;
1117 			const int	numColumns	= 4;
1118 			const float	quadSide	= 0.15f;
1119 			de::Random	rnd			(0xabcd);
1120 
1121 			outData.resize(6 * numRows * numColumns);
1122 
1123 			for (int col = 0; col < numColumns; ++col)
1124 			for (int row = 0; row < numRows;    ++row)
1125 			{
1126 				const tcu::Vec2 center		= tcu::Vec2((row + 0.5f) / numRows * 2.0f - 1.0f, (col + 0.5f) / numColumns * 2.0f - 1.0f);
1127 				const float		rotation	= (iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1128 				const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1129 				const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
1130 				const tcu::Vec2 quad[4]		=
1131 				{
1132 					center + sideH + sideV,
1133 					center + sideH - sideV,
1134 					center - sideH - sideV,
1135 					center - sideH + sideV,
1136 				};
1137 
1138 				if (m_caseType == FILLRULECASE_BASIC)
1139 				{
1140 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1141 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1142 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1143 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1144 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1145 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1146 				}
1147 				else if (m_caseType == FILLRULECASE_REVERSED)
1148 				{
1149 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1150 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1151 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1152 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1153 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1154 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1155 				}
1156 				else if (m_caseType == FILLRULECASE_PROJECTED)
1157 				{
1158 					const float w0 = rnd.getFloat(0.1f, 4.0f);
1159 					const float w1 = rnd.getFloat(0.1f, 4.0f);
1160 					const float w2 = rnd.getFloat(0.1f, 4.0f);
1161 					const float w3 = rnd.getFloat(0.1f, 4.0f);
1162 
1163 					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1164 					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1165 					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1166 					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1167 					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1168 					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1169 				}
1170 				else
1171 					DE_ASSERT(DE_FALSE);
1172 			}
1173 
1174 			break;
1175 		}
1176 
1177 		case FILLRULECASE_CLIPPED_PARTIAL:
1178 		case FILLRULECASE_CLIPPED_FULL:
1179 		{
1180 			const float		quadSide	= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1181 			const tcu::Vec2 center		= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1182 			const float		rotation	= (iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1183 			const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1184 			const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
1185 			const tcu::Vec2 quad[4]		=
1186 			{
1187 				center + sideH + sideV,
1188 				center + sideH - sideV,
1189 				center - sideH - sideV,
1190 				center - sideH + sideV,
1191 			};
1192 
1193 			outData.resize(6);
1194 			outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1195 			outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1196 			outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1197 			outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1198 			outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1199 			outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1200 			break;
1201 		}
1202 
1203 		default:
1204 			DE_ASSERT(DE_FALSE);
1205 	}
1206 }
1207 
1208 class CullingTest : public BaseRenderingCase
1209 {
1210 public:
1211 						CullingTest			(Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder);
1212 						~CullingTest		(void);
1213 	IterateResult		iterate				(void);
1214 
1215 private:
1216 	void				generateVertices	(std::vector<tcu::Vec4>& outData) const;
1217 	void				extractTriangles	(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1218 	bool				triangleOrder		(const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1219 
1220 	const glw::GLenum	m_cullMode;
1221 	const glw::GLenum	m_primitive;
1222 	const glw::GLenum	m_faceOrder;
1223 };
1224 
CullingTest(Context & ctx,const char * name,const char * desc,glw::GLenum cullMode,glw::GLenum primitive,glw::GLenum faceOrder)1225 CullingTest::CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder)
1226 	: BaseRenderingCase	(ctx, name, desc)
1227 	, m_cullMode		(cullMode)
1228 	, m_primitive		(primitive)
1229 	, m_faceOrder		(faceOrder)
1230 {
1231 }
1232 
~CullingTest(void)1233 CullingTest::~CullingTest (void)
1234 {
1235 }
1236 
iterate(void)1237 CullingTest::IterateResult CullingTest::iterate (void)
1238 {
1239 	tcu::Surface									resultImage(m_renderSize, m_renderSize);
1240 	std::vector<tcu::Vec4>							drawBuffer;
1241 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
1242 
1243 	// generate scene
1244 	generateVertices(drawBuffer);
1245 	extractTriangles(triangles, drawBuffer);
1246 
1247 	// draw image
1248 	{
1249 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1250 
1251 		gl.enable(GL_CULL_FACE);
1252 		gl.cullFace(m_cullMode);
1253 		gl.frontFace(m_faceOrder);
1254 
1255 		m_testCtx.getLog() << tcu::TestLog::Message << "Setting front face to " << glu::getWindingName(m_faceOrder) << tcu::TestLog::EndMessage;
1256 		m_testCtx.getLog() << tcu::TestLog::Message << "Setting cull face to " << glu::getFaceName(m_cullMode) << tcu::TestLog::EndMessage;
1257 		m_testCtx.getLog() << tcu::TestLog::Message << "Drawing test pattern (" << glu::getPrimitiveTypeName(m_primitive) << ")" << tcu::TestLog::EndMessage;
1258 
1259 		drawPrimitives(resultImage, drawBuffer, m_primitive);
1260 	}
1261 
1262 	// compare
1263 	{
1264 		RasterizationArguments	args;
1265 		TriangleSceneSpec		scene;
1266 
1267 		args.numSamples		= m_numSamples;
1268 		args.subpixelBits	= m_subpixelBits;
1269 		args.redBits		= m_context.getRenderTarget().getPixelFormat().redBits;
1270 		args.greenBits		= m_context.getRenderTarget().getPixelFormat().greenBits;
1271 		args.blueBits		= m_context.getRenderTarget().getPixelFormat().blueBits;
1272 
1273 		scene.triangles.swap(triangles);
1274 
1275 		if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), VERIFICATIONMODE_WEAK))
1276 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1277 		else
1278 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering");
1279 	}
1280 
1281 	return STOP;
1282 }
1283 
generateVertices(std::vector<tcu::Vec4> & outData) const1284 void CullingTest::generateVertices (std::vector<tcu::Vec4>& outData) const
1285 {
1286 	de::Random rnd(543210);
1287 
1288 	outData.resize(6);
1289 	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1290 	{
1291 		outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1292 		outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1293 		outData[vtxNdx].z() = 0.0f;
1294 		outData[vtxNdx].w() = 1.0f;
1295 	}
1296 }
1297 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices) const1298 void CullingTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
1299 {
1300 	const bool cullDirection = (m_cullMode == GL_FRONT) ^ (m_faceOrder == GL_CCW);
1301 
1302 	// No triangles
1303 	if (m_cullMode == GL_FRONT_AND_BACK)
1304 		return;
1305 
1306 	switch (m_primitive)
1307 	{
1308 		case GL_TRIANGLES:
1309 		{
1310 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1311 			{
1312 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1313 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1314 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1315 
1316 				if (triangleOrder(v0, v1, v2) != cullDirection)
1317 				{
1318 					TriangleSceneSpec::SceneTriangle tri;
1319 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
1320 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
1321 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
1322 
1323 					outTriangles.push_back(tri);
1324 				}
1325 			}
1326 			break;
1327 		}
1328 
1329 		case GL_TRIANGLE_STRIP:
1330 		{
1331 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1332 			{
1333 				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1334 				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1335 				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1336 
1337 				if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
1338 				{
1339 					TriangleSceneSpec::SceneTriangle tri;
1340 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
1341 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
1342 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
1343 
1344 					outTriangles.push_back(tri);
1345 				}
1346 			}
1347 			break;
1348 		}
1349 
1350 		case GL_TRIANGLE_FAN:
1351 		{
1352 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1353 			{
1354 				const tcu::Vec4& v0 = vertices[0];
1355 				const tcu::Vec4& v1 = vertices[vtxNdx + 0];
1356 				const tcu::Vec4& v2 = vertices[vtxNdx + 1];
1357 
1358 				if (triangleOrder(v0, v1, v2) != cullDirection)
1359 				{
1360 					TriangleSceneSpec::SceneTriangle tri;
1361 					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
1362 					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
1363 					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
1364 
1365 					outTriangles.push_back(tri);
1366 				}
1367 			}
1368 			break;
1369 		}
1370 
1371 		default:
1372 			DE_ASSERT(false);
1373 	}
1374 }
1375 
triangleOrder(const tcu::Vec4 & v0,const tcu::Vec4 & v1,const tcu::Vec4 & v2) const1376 bool CullingTest::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
1377 {
1378 	const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
1379 	const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
1380 	const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
1381 
1382 	// cross
1383 	return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) < 0;
1384 }
1385 
1386 class TriangleInterpolationTest : public BaseRenderingCase
1387 {
1388 public:
1389 						TriangleInterpolationTest	(Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags);
1390 						~TriangleInterpolationTest	(void);
1391 	IterateResult		iterate						(void);
1392 
1393 private:
1394 	void				generateVertices			(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1395 	void				extractTriangles			(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1396 
1397 	const glw::GLenum	m_primitive;
1398 	const bool			m_projective;
1399 	const int			m_iterationCount;
1400 
1401 	int					m_iteration;
1402 	bool				m_allIterationsPassed;
1403 };
1404 
TriangleInterpolationTest(Context & ctx,const char * name,const char * desc,glw::GLenum primitive,int flags)1405 TriangleInterpolationTest::TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags)
1406 	: BaseRenderingCase		(ctx, name, desc)
1407 	, m_primitive			(primitive)
1408 	, m_projective			((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1409 	, m_iterationCount		(3)
1410 	, m_iteration			(0)
1411 	, m_allIterationsPassed	(true)
1412 {
1413 }
1414 
~TriangleInterpolationTest(void)1415 TriangleInterpolationTest::~TriangleInterpolationTest (void)
1416 {
1417 	deinit();
1418 }
1419 
iterate(void)1420 TriangleInterpolationTest::IterateResult TriangleInterpolationTest::iterate (void)
1421 {
1422 	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1423 	const tcu::ScopedLogSection						section					(m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1424 	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
1425 	std::vector<tcu::Vec4>							drawBuffer;
1426 	std::vector<tcu::Vec4>							colorBuffer;
1427 	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
1428 
1429 	// generate scene
1430 	generateVertices(m_iteration, drawBuffer, colorBuffer);
1431 	extractTriangles(triangles, drawBuffer, colorBuffer);
1432 
1433 	// log
1434 	{
1435 		m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1436 		for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1437 			m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1438 	}
1439 
1440 	// draw image
1441 	drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1442 
1443 	// compare
1444 	{
1445 		RasterizationArguments	args;
1446 		TriangleSceneSpec		scene;
1447 
1448 		args.numSamples		= m_numSamples;
1449 		args.subpixelBits	= m_subpixelBits;
1450 		args.redBits		= m_context.getRenderTarget().getPixelFormat().redBits;
1451 		args.greenBits		= m_context.getRenderTarget().getPixelFormat().greenBits;
1452 		args.blueBits		= m_context.getRenderTarget().getPixelFormat().blueBits;
1453 
1454 		scene.triangles.swap(triangles);
1455 
1456 		if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_testCtx.getLog()))
1457 			m_allIterationsPassed = false;
1458 	}
1459 
1460 	// result
1461 	if (++m_iteration == m_iterationCount)
1462 	{
1463 		if (m_allIterationsPassed)
1464 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1465 		else
1466 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1467 
1468 		return STOP;
1469 	}
1470 	else
1471 		return CONTINUE;
1472 }
1473 
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const1474 void TriangleInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1475 {
1476 	// use only red, green and blue
1477 	const tcu::Vec4 colors[] =
1478 	{
1479 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1480 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1481 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1482 	};
1483 
1484 	de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1485 
1486 	outVertices.resize(6);
1487 	outColors.resize(6);
1488 
1489 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1490 	{
1491 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1492 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1493 		outVertices[vtxNdx].z() = 0.0f;
1494 
1495 		if (!m_projective)
1496 			outVertices[vtxNdx].w() = 1.0f;
1497 		else
1498 		{
1499 			const float w = rnd.getFloat(0.2f, 4.0f);
1500 
1501 			outVertices[vtxNdx].x() *= w;
1502 			outVertices[vtxNdx].y() *= w;
1503 			outVertices[vtxNdx].z() *= w;
1504 			outVertices[vtxNdx].w() = w;
1505 		}
1506 
1507 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1508 	}
1509 }
1510 
extractTriangles(std::vector<TriangleSceneSpec::SceneTriangle> & outTriangles,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const1511 void TriangleInterpolationTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1512 {
1513 	switch (m_primitive)
1514 	{
1515 		case GL_TRIANGLES:
1516 		{
1517 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1518 			{
1519 				TriangleSceneSpec::SceneTriangle tri;
1520 				tri.positions[0]	= vertices[vtxNdx + 0];
1521 				tri.positions[1]	= vertices[vtxNdx + 1];
1522 				tri.positions[2]	= vertices[vtxNdx + 2];
1523 				tri.sharedEdge[0]	= false;
1524 				tri.sharedEdge[1]	= false;
1525 				tri.sharedEdge[2]	= false;
1526 
1527 				tri.colors[0] = colors[vtxNdx + 0];
1528 				tri.colors[1] = colors[vtxNdx + 1];
1529 				tri.colors[2] = colors[vtxNdx + 2];
1530 
1531 				outTriangles.push_back(tri);
1532 			}
1533 			break;
1534 		}
1535 
1536 		case GL_TRIANGLE_STRIP:
1537 		{
1538 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1539 			{
1540 				TriangleSceneSpec::SceneTriangle tri;
1541 				tri.positions[0]	= vertices[vtxNdx + 0];
1542 				tri.positions[1]	= vertices[vtxNdx + 1];
1543 				tri.positions[2]	= vertices[vtxNdx + 2];
1544 				tri.sharedEdge[0]	= false;
1545 				tri.sharedEdge[1]	= false;
1546 				tri.sharedEdge[2]	= false;
1547 
1548 				tri.colors[0] = colors[vtxNdx + 0];
1549 				tri.colors[1] = colors[vtxNdx + 1];
1550 				tri.colors[2] = colors[vtxNdx + 2];
1551 
1552 				outTriangles.push_back(tri);
1553 			}
1554 			break;
1555 		}
1556 
1557 		case GL_TRIANGLE_FAN:
1558 		{
1559 			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1560 			{
1561 				TriangleSceneSpec::SceneTriangle tri;
1562 				tri.positions[0]	= vertices[0];
1563 				tri.positions[1]	= vertices[vtxNdx + 0];
1564 				tri.positions[2]	= vertices[vtxNdx + 1];
1565 				tri.sharedEdge[0]	= false;
1566 				tri.sharedEdge[1]	= false;
1567 				tri.sharedEdge[2]	= false;
1568 
1569 				tri.colors[0] = colors[0];
1570 				tri.colors[1] = colors[vtxNdx + 0];
1571 				tri.colors[2] = colors[vtxNdx + 1];
1572 
1573 				outTriangles.push_back(tri);
1574 			}
1575 			break;
1576 		}
1577 
1578 		default:
1579 			DE_ASSERT(false);
1580 	}
1581 }
1582 
1583 class LineInterpolationTest : public BaseRenderingCase
1584 {
1585 public:
1586 						LineInterpolationTest	(Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth);
1587 						~LineInterpolationTest	(void);
1588 	IterateResult		iterate					(void);
1589 
1590 private:
1591 	void				generateVertices		(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1592 	void				extractLines			(std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1593 
1594 	const glw::GLenum	m_primitive;
1595 	const bool			m_projective;
1596 	const int			m_iterationCount;
1597 
1598 	int					m_iteration;
1599 	bool				m_allIterationsPassed;
1600 };
1601 
LineInterpolationTest(Context & ctx,const char * name,const char * desc,glw::GLenum primitive,int flags,float lineWidth)1602 LineInterpolationTest::LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, float lineWidth)
1603 	: BaseRenderingCase		(ctx, name, desc)
1604 	, m_primitive			(primitive)
1605 	, m_projective			((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1606 	, m_iterationCount		(3)
1607 	, m_iteration			(0)
1608 	, m_allIterationsPassed	(true)
1609 {
1610 	m_lineWidth = lineWidth;
1611 }
1612 
~LineInterpolationTest(void)1613 LineInterpolationTest::~LineInterpolationTest (void)
1614 {
1615 	deinit();
1616 }
1617 
iterate(void)1618 LineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
1619 {
1620 	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1621 	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1622 	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
1623 	std::vector<tcu::Vec4>					drawBuffer;
1624 	std::vector<tcu::Vec4>					colorBuffer;
1625 	std::vector<LineSceneSpec::SceneLine>	lines;
1626 
1627 	// generate scene
1628 	generateVertices(m_iteration, drawBuffer, colorBuffer);
1629 	extractLines(lines, drawBuffer, colorBuffer);
1630 
1631 	// log
1632 	{
1633 		m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1634 		for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1635 			m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1636 	}
1637 
1638 	// draw image
1639 	drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1640 
1641 	// compare
1642 	{
1643 		RasterizationArguments	args;
1644 		LineSceneSpec			scene;
1645 
1646 		args.numSamples		= m_numSamples;
1647 		args.subpixelBits	= m_subpixelBits;
1648 		args.redBits		= m_context.getRenderTarget().getPixelFormat().redBits;
1649 		args.greenBits		= m_context.getRenderTarget().getPixelFormat().greenBits;
1650 		args.blueBits		= m_context.getRenderTarget().getPixelFormat().blueBits;
1651 
1652 		scene.lines.swap(lines);
1653 		scene.lineWidth = m_lineWidth;
1654 
1655 		if (!verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog()))
1656 			m_allIterationsPassed = false;
1657 	}
1658 
1659 	// result
1660 	if (++m_iteration == m_iterationCount)
1661 	{
1662 		if (m_allIterationsPassed)
1663 			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1664 		else
1665 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1666 
1667 		return STOP;
1668 	}
1669 	else
1670 		return CONTINUE;
1671 }
1672 
generateVertices(int iteration,std::vector<tcu::Vec4> & outVertices,std::vector<tcu::Vec4> & outColors) const1673 void LineInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1674 {
1675 	// use only red, green and blue
1676 	const tcu::Vec4 colors[] =
1677 	{
1678 		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1679 		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1680 		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1681 	};
1682 
1683 	de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1684 
1685 	outVertices.resize(6);
1686 	outColors.resize(6);
1687 
1688 	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1689 	{
1690 		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1691 		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1692 		outVertices[vtxNdx].z() = 0.0f;
1693 
1694 		if (!m_projective)
1695 			outVertices[vtxNdx].w() = 1.0f;
1696 		else
1697 		{
1698 			const float w = rnd.getFloat(0.2f, 4.0f);
1699 
1700 			outVertices[vtxNdx].x() *= w;
1701 			outVertices[vtxNdx].y() *= w;
1702 			outVertices[vtxNdx].z() *= w;
1703 			outVertices[vtxNdx].w() = w;
1704 		}
1705 
1706 		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1707 	}
1708 }
1709 
extractLines(std::vector<LineSceneSpec::SceneLine> & outLines,const std::vector<tcu::Vec4> & vertices,const std::vector<tcu::Vec4> & colors) const1710 void LineInterpolationTest::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1711 {
1712 	switch (m_primitive)
1713 	{
1714 		case GL_LINES:
1715 		{
1716 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
1717 			{
1718 				LineSceneSpec::SceneLine line;
1719 				line.positions[0] = vertices[vtxNdx + 0];
1720 				line.positions[1] = vertices[vtxNdx + 1];
1721 
1722 				line.colors[0] = colors[vtxNdx + 0];
1723 				line.colors[1] = colors[vtxNdx + 1];
1724 
1725 				outLines.push_back(line);
1726 			}
1727 			break;
1728 		}
1729 
1730 		case GL_LINE_STRIP:
1731 		{
1732 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1733 			{
1734 				LineSceneSpec::SceneLine line;
1735 				line.positions[0] = vertices[vtxNdx + 0];
1736 				line.positions[1] = vertices[vtxNdx + 1];
1737 
1738 				line.colors[0] = colors[vtxNdx + 0];
1739 				line.colors[1] = colors[vtxNdx + 1];
1740 
1741 				outLines.push_back(line);
1742 			}
1743 			break;
1744 		}
1745 
1746 		case GL_LINE_LOOP:
1747 		{
1748 			for (int vtxNdx = 0; vtxNdx < (int)vertices.size(); ++vtxNdx)
1749 			{
1750 				LineSceneSpec::SceneLine line;
1751 				line.positions[0] = vertices[(vtxNdx + 0) % (int)vertices.size()];
1752 				line.positions[1] = vertices[(vtxNdx + 1) % (int)vertices.size()];
1753 
1754 				line.colors[0] = colors[(vtxNdx + 0) % (int)vertices.size()];
1755 				line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()];
1756 
1757 				outLines.push_back(line);
1758 			}
1759 			break;
1760 		}
1761 
1762 		default:
1763 			DE_ASSERT(false);
1764 	}
1765 }
1766 
1767 } // anonymous
1768 
RasterizationTests(Context & context)1769 RasterizationTests::RasterizationTests (Context& context)
1770 	: TestCaseGroup(context, "rasterization", "Rasterization Tests")
1771 {
1772 }
1773 
~RasterizationTests(void)1774 RasterizationTests::~RasterizationTests (void)
1775 {
1776 }
1777 
init(void)1778 void RasterizationTests::init (void)
1779 {
1780 	// .primitives
1781 	{
1782 		tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization");
1783 
1784 		addChild(primitives);
1785 
1786 		primitives->addChild(new TrianglesCase		(m_context, "triangles",		"Render primitives as GL_TRIANGLES, verify rasterization result"));
1787 		primitives->addChild(new TriangleStripCase	(m_context, "triangle_strip",	"Render primitives as GL_TRIANGLE_STRIP, verify rasterization result"));
1788 		primitives->addChild(new TriangleFanCase	(m_context, "triangle_fan",		"Render primitives as GL_TRIANGLE_FAN, verify rasterization result"));
1789 		primitives->addChild(new LinesCase			(m_context, "lines",			"Render primitives as GL_LINES, verify rasterization result",							PRIMITIVEWIDENESS_NARROW));
1790 		primitives->addChild(new LineStripCase		(m_context, "line_strip",		"Render primitives as GL_LINE_STRIP, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
1791 		primitives->addChild(new LineLoopCase		(m_context, "line_loop",		"Render primitives as GL_LINE_LOOP, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
1792 		primitives->addChild(new LinesCase			(m_context, "lines_wide",		"Render primitives as GL_LINES with wide lines, verify rasterization result",			PRIMITIVEWIDENESS_WIDE));
1793 		primitives->addChild(new LineStripCase		(m_context, "line_strip_wide",	"Render primitives as GL_LINE_STRIP with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE));
1794 		primitives->addChild(new LineLoopCase		(m_context, "line_loop_wide",	"Render primitives as GL_LINE_LOOP with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE));
1795 		primitives->addChild(new PointCase			(m_context, "points",			"Render primitives as GL_POINTS, verify rasterization result",							PRIMITIVEWIDENESS_WIDE));
1796 	}
1797 
1798 	// .fill_rules
1799 	{
1800 		tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules");
1801 
1802 		addChild(fillRules);
1803 
1804 		fillRules->addChild(new FillRuleCase(m_context,	"basic_quad",			"Verify fill rules",	FillRuleCase::FILLRULECASE_BASIC));
1805 		fillRules->addChild(new FillRuleCase(m_context,	"basic_quad_reverse",	"Verify fill rules",	FillRuleCase::FILLRULECASE_REVERSED));
1806 		fillRules->addChild(new FillRuleCase(m_context,	"clipped_full",			"Verify fill rules",	FillRuleCase::FILLRULECASE_CLIPPED_FULL));
1807 		fillRules->addChild(new FillRuleCase(m_context,	"clipped_partly",		"Verify fill rules",	FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL));
1808 		fillRules->addChild(new FillRuleCase(m_context,	"projected",			"Verify fill rules",	FillRuleCase::FILLRULECASE_PROJECTED));
1809 	}
1810 
1811 	// .culling
1812 	{
1813 		static const struct CullMode
1814 		{
1815 			glw::GLenum	mode;
1816 			const char*	prefix;
1817 		} cullModes[] =
1818 		{
1819 			{ GL_FRONT,				"front_"	},
1820 			{ GL_BACK,				"back_"		},
1821 			{ GL_FRONT_AND_BACK,	"both_"		},
1822 		};
1823 		static const struct PrimitiveType
1824 		{
1825 			glw::GLenum	type;
1826 			const char*	name;
1827 		} primitiveTypes[] =
1828 		{
1829 			{ GL_TRIANGLES,			"triangles"			},
1830 			{ GL_TRIANGLE_STRIP,	"triangle_strip"	},
1831 			{ GL_TRIANGLE_FAN,		"triangle_fan"		},
1832 		};
1833 		static const struct FrontFaceOrder
1834 		{
1835 			glw::GLenum	mode;
1836 			const char*	postfix;
1837 		} frontOrders[] =
1838 		{
1839 			{ GL_CCW,	""			},
1840 			{ GL_CW,	"_reverse"	},
1841 		};
1842 
1843 		tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(m_testCtx, "culling", "Culling");
1844 
1845 		addChild(culling);
1846 
1847 		for (int cullModeNdx   = 0; cullModeNdx   < DE_LENGTH_OF_ARRAY(cullModes);      ++cullModeNdx)
1848 		for (int primitiveNdx  = 0; primitiveNdx  < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
1849 		for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders);    ++frontOrderNdx)
1850 		{
1851 			const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix;
1852 
1853 			culling->addChild(new CullingTest(m_context, name.c_str(), "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode));
1854 		}
1855 	}
1856 
1857 	// .interpolation
1858 	{
1859 		tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Test interpolation");
1860 
1861 		addChild(interpolation);
1862 
1863 		// .basic
1864 		{
1865 			tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(m_testCtx, "basic", "Non-projective interpolation");
1866 
1867 			interpolation->addChild(basic);
1868 
1869 			basic->addChild(new TriangleInterpolationTest		(m_context, "triangles",		"Verify triangle interpolation",		GL_TRIANGLES,		INTERPOLATIONFLAGS_NONE));
1870 			basic->addChild(new TriangleInterpolationTest		(m_context, "triangle_strip",	"Verify triangle strip interpolation",	GL_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_NONE));
1871 			basic->addChild(new TriangleInterpolationTest		(m_context, "triangle_fan",		"Verify triangle fan interpolation",	GL_TRIANGLE_FAN,	INTERPOLATIONFLAGS_NONE));
1872 			basic->addChild(new LineInterpolationTest			(m_context, "lines",			"Verify line interpolation",			GL_LINES,			INTERPOLATIONFLAGS_NONE,	1.0f));
1873 			basic->addChild(new LineInterpolationTest			(m_context, "line_strip",		"Verify line strip interpolation",		GL_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	1.0f));
1874 			basic->addChild(new LineInterpolationTest			(m_context, "line_loop",		"Verify line loop interpolation",		GL_LINE_LOOP,		INTERPOLATIONFLAGS_NONE,	1.0f));
1875 			basic->addChild(new LineInterpolationTest			(m_context, "lines_wide",		"Verify wide line interpolation",		GL_LINES,			INTERPOLATIONFLAGS_NONE,	5.0f));
1876 			basic->addChild(new LineInterpolationTest			(m_context, "line_strip_wide",	"Verify wide line strip interpolation",	GL_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	5.0f));
1877 			basic->addChild(new LineInterpolationTest			(m_context, "line_loop_wide",	"Verify wide line loop interpolation",	GL_LINE_LOOP,		INTERPOLATIONFLAGS_NONE,	5.0f));
1878 		}
1879 
1880 		// .projected
1881 		{
1882 			tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(m_testCtx, "projected", "Projective interpolation");
1883 
1884 			interpolation->addChild(projected);
1885 
1886 			projected->addChild(new TriangleInterpolationTest	(m_context, "triangles",		"Verify triangle interpolation",		GL_TRIANGLES,		INTERPOLATIONFLAGS_PROJECTED));
1887 			projected->addChild(new TriangleInterpolationTest	(m_context, "triangle_strip",	"Verify triangle strip interpolation",	GL_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_PROJECTED));
1888 			projected->addChild(new TriangleInterpolationTest	(m_context, "triangle_fan",		"Verify triangle fan interpolation",	GL_TRIANGLE_FAN,	INTERPOLATIONFLAGS_PROJECTED));
1889 			projected->addChild(new LineInterpolationTest		(m_context, "lines",			"Verify line interpolation",			GL_LINES,			INTERPOLATIONFLAGS_PROJECTED,	1.0f));
1890 			projected->addChild(new LineInterpolationTest		(m_context, "line_strip",		"Verify line strip interpolation",		GL_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	1.0f));
1891 			projected->addChild(new LineInterpolationTest		(m_context, "line_loop",		"Verify line loop interpolation",		GL_LINE_LOOP,		INTERPOLATIONFLAGS_PROJECTED,	1.0f));
1892 			projected->addChild(new LineInterpolationTest		(m_context, "lines_wide",		"Verify wide line interpolation",		GL_LINES,			INTERPOLATIONFLAGS_PROJECTED,	5.0f));
1893 			projected->addChild(new LineInterpolationTest		(m_context, "line_strip_wide",	"Verify wide line strip interpolation",	GL_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	5.0f));
1894 			projected->addChild(new LineInterpolationTest		(m_context, "line_loop_wide",	"Verify wide line loop interpolation",	GL_LINE_LOOP,		INTERPOLATIONFLAGS_PROJECTED,	5.0f));
1895 		}
1896 	}
1897 }
1898 
1899 } // Functional
1900 } // gles2
1901 } // deqp
1902