1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.0 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Functional rasterization tests.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es3fRasterizationTests.hpp"
25e5c31af7Sopenharmony_ci#include "tcuRasterizationVerifier.hpp"
26e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
27e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
28e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
29e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
30e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
31e5c31af7Sopenharmony_ci#include "tcuResultCollector.hpp"
32e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
33e5c31af7Sopenharmony_ci#include "gluRenderContext.hpp"
34e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
35e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp"
36e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp"
37e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
38e5c31af7Sopenharmony_ci#include "deRandom.hpp"
39e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
40e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci#include <vector>
43e5c31af7Sopenharmony_ci
44e5c31af7Sopenharmony_cinamespace deqp
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_cinamespace gles3
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_cinamespace Functional
49e5c31af7Sopenharmony_ci{
50e5c31af7Sopenharmony_cinamespace
51e5c31af7Sopenharmony_ci{
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_ciusing tcu::RasterizationArguments;
54e5c31af7Sopenharmony_ciusing tcu::TriangleSceneSpec;
55e5c31af7Sopenharmony_ciusing tcu::PointSceneSpec;
56e5c31af7Sopenharmony_ciusing tcu::LineSceneSpec;
57e5c31af7Sopenharmony_ciusing tcu::LineInterpolationMethod;
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_cistatic const char* const s_shaderVertexTemplate =	"#version 300 es\n"
60e5c31af7Sopenharmony_ci													"in highp vec4 a_position;\n"
61e5c31af7Sopenharmony_ci													"in highp vec4 a_color;\n"
62e5c31af7Sopenharmony_ci													"${INTERPOLATION}out highp vec4 v_color;\n"
63e5c31af7Sopenharmony_ci													"uniform highp float u_pointSize;\n"
64e5c31af7Sopenharmony_ci													"void main ()\n"
65e5c31af7Sopenharmony_ci													"{\n"
66e5c31af7Sopenharmony_ci													"	gl_Position = a_position;\n"
67e5c31af7Sopenharmony_ci													"	gl_PointSize = u_pointSize;\n"
68e5c31af7Sopenharmony_ci													"	v_color = a_color;\n"
69e5c31af7Sopenharmony_ci													"}\n";
70e5c31af7Sopenharmony_cistatic const char* const s_shaderFragmentTemplate =	"#version 300 es\n"
71e5c31af7Sopenharmony_ci													"layout(location = 0) out highp vec4 fragColor;\n"
72e5c31af7Sopenharmony_ci													"${INTERPOLATION}in highp vec4 v_color;\n"
73e5c31af7Sopenharmony_ci													"void main ()\n"
74e5c31af7Sopenharmony_ci													"{\n"
75e5c31af7Sopenharmony_ci													"	fragColor = v_color;\n"
76e5c31af7Sopenharmony_ci													"}\n";
77e5c31af7Sopenharmony_cienum InterpolationCaseFlags
78e5c31af7Sopenharmony_ci{
79e5c31af7Sopenharmony_ci	INTERPOLATIONFLAGS_NONE = 0,
80e5c31af7Sopenharmony_ci	INTERPOLATIONFLAGS_PROJECTED = (1 << 1),
81e5c31af7Sopenharmony_ci	INTERPOLATIONFLAGS_FLATSHADE = (1 << 2),
82e5c31af7Sopenharmony_ci};
83e5c31af7Sopenharmony_ci
84e5c31af7Sopenharmony_cienum PrimitiveWideness
85e5c31af7Sopenharmony_ci{
86e5c31af7Sopenharmony_ci	PRIMITIVEWIDENESS_NARROW = 0,
87e5c31af7Sopenharmony_ci	PRIMITIVEWIDENESS_WIDE,
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci	PRIMITIVEWIDENESS_LAST
90e5c31af7Sopenharmony_ci};
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_cistatic tcu::PixelFormat getInternalFormatPixelFormat (glw::GLenum internalFormat)
93e5c31af7Sopenharmony_ci{
94e5c31af7Sopenharmony_ci	const tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(glu::mapGLInternalFormat(internalFormat));
95e5c31af7Sopenharmony_ci	return tcu::PixelFormat(bitDepth.x(), bitDepth.y(), bitDepth.z(), bitDepth.w());
96e5c31af7Sopenharmony_ci}
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ciclass BaseRenderingCase : public TestCase
99e5c31af7Sopenharmony_ci{
100e5c31af7Sopenharmony_cipublic:
101e5c31af7Sopenharmony_ci	enum RenderTarget
102e5c31af7Sopenharmony_ci	{
103e5c31af7Sopenharmony_ci		RENDERTARGET_DEFAULT = 0,
104e5c31af7Sopenharmony_ci		RENDERTARGET_TEXTURE_2D,
105e5c31af7Sopenharmony_ci		RENDERTARGET_RBO_SINGLESAMPLE,
106e5c31af7Sopenharmony_ci		RENDERTARGET_RBO_MULTISAMPLE,
107e5c31af7Sopenharmony_ci
108e5c31af7Sopenharmony_ci		RENDERTARGET_LAST
109e5c31af7Sopenharmony_ci	};
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_ci	enum
112e5c31af7Sopenharmony_ci	{
113e5c31af7Sopenharmony_ci		DEFAULT_RENDER_SIZE = 256,
114e5c31af7Sopenharmony_ci		SAMPLE_COUNT_MAX = -2,
115e5c31af7Sopenharmony_ci	};
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci							BaseRenderingCase	(Context& context, const char* name, const char* desc, RenderTarget target, int numSamples, int renderSize);
118e5c31af7Sopenharmony_ci							~BaseRenderingCase	(void);
119e5c31af7Sopenharmony_ci	virtual void			init				(void);
120e5c31af7Sopenharmony_ci	void					deinit				(void);
121e5c31af7Sopenharmony_ci
122e5c31af7Sopenharmony_ciprotected:
123e5c31af7Sopenharmony_ci	void					drawPrimitives		(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType);
124e5c31af7Sopenharmony_ci	void					drawPrimitives		(tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& coloDrata, glw::GLenum primitiveType);
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ci	virtual float			getLineWidth		(void) const;
127e5c31af7Sopenharmony_ci	virtual float			getPointSize		(void) const;
128e5c31af7Sopenharmony_ci	const tcu::PixelFormat&	getPixelFormat		(void) const;
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_ci	const int				m_renderSize;
131e5c31af7Sopenharmony_ci	int						m_numSamples;
132e5c31af7Sopenharmony_ci	int						m_subpixelBits;
133e5c31af7Sopenharmony_ci	bool					m_flatshade;
134e5c31af7Sopenharmony_ci	const int				m_numRequestedSamples;
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_ciprivate:
137e5c31af7Sopenharmony_ci	const RenderTarget		m_renderTarget;
138e5c31af7Sopenharmony_ci	const glw::GLenum		m_fboInternalFormat;
139e5c31af7Sopenharmony_ci	const tcu::PixelFormat	m_pixelFormat;
140e5c31af7Sopenharmony_ci	glu::ShaderProgram*		m_shader;
141e5c31af7Sopenharmony_ci	glw::GLuint				m_fbo;
142e5c31af7Sopenharmony_ci	glw::GLuint				m_texture;
143e5c31af7Sopenharmony_ci	glw::GLuint				m_rbo;
144e5c31af7Sopenharmony_ci	glw::GLuint				m_blitDstFbo;
145e5c31af7Sopenharmony_ci	glw::GLuint				m_blitDstRbo;
146e5c31af7Sopenharmony_ci};
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ciBaseRenderingCase::BaseRenderingCase (Context& context, const char* name, const char* desc, RenderTarget target, int numSamples, int renderSize)
149e5c31af7Sopenharmony_ci	: TestCase				(context, name, desc)
150e5c31af7Sopenharmony_ci	, m_renderSize			(renderSize)
151e5c31af7Sopenharmony_ci	, m_numSamples			(-1)
152e5c31af7Sopenharmony_ci	, m_subpixelBits		(-1)
153e5c31af7Sopenharmony_ci	, m_flatshade			(false)
154e5c31af7Sopenharmony_ci	, m_numRequestedSamples	(numSamples)
155e5c31af7Sopenharmony_ci	, m_renderTarget		(target)
156e5c31af7Sopenharmony_ci	, m_fboInternalFormat	(GL_RGBA8)
157e5c31af7Sopenharmony_ci	, m_pixelFormat			((m_renderTarget == RENDERTARGET_DEFAULT) ? (m_context.getRenderTarget().getPixelFormat()) : (getInternalFormatPixelFormat(m_fboInternalFormat)))
158e5c31af7Sopenharmony_ci	, m_shader				(DE_NULL)
159e5c31af7Sopenharmony_ci	, m_fbo					(0)
160e5c31af7Sopenharmony_ci	, m_texture				(0)
161e5c31af7Sopenharmony_ci	, m_rbo					(0)
162e5c31af7Sopenharmony_ci	, m_blitDstFbo			(0)
163e5c31af7Sopenharmony_ci	, m_blitDstRbo			(0)
164e5c31af7Sopenharmony_ci{
165e5c31af7Sopenharmony_ci	DE_ASSERT(m_renderTarget < RENDERTARGET_LAST);
166e5c31af7Sopenharmony_ci	DE_ASSERT((m_numRequestedSamples == -1) == (m_renderTarget != RENDERTARGET_RBO_MULTISAMPLE));
167e5c31af7Sopenharmony_ci}
168e5c31af7Sopenharmony_ci
169e5c31af7Sopenharmony_ciBaseRenderingCase::~BaseRenderingCase (void)
170e5c31af7Sopenharmony_ci{
171e5c31af7Sopenharmony_ci	deinit();
172e5c31af7Sopenharmony_ci}
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_civoid BaseRenderingCase::init (void)
175e5c31af7Sopenharmony_ci{
176e5c31af7Sopenharmony_ci	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
177e5c31af7Sopenharmony_ci	const int				width					= m_context.getRenderTarget().getWidth();
178e5c31af7Sopenharmony_ci	const int				height					= m_context.getRenderTarget().getHeight();
179e5c31af7Sopenharmony_ci	int						msaaTargetSamples		= -1;
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ci	// Requirements
182e5c31af7Sopenharmony_ci
183e5c31af7Sopenharmony_ci	if (m_renderTarget == RENDERTARGET_DEFAULT && (width < m_renderSize || height < m_renderSize))
184e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError(std::string("Render target size must be at least ") + de::toString(m_renderSize) + "x" + de::toString(m_renderSize));
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci	if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
187e5c31af7Sopenharmony_ci	{
188e5c31af7Sopenharmony_ci		glw::GLint maxSampleCount = 0;
189e5c31af7Sopenharmony_ci		gl.getInternalformativ(GL_RENDERBUFFER, m_fboInternalFormat, GL_SAMPLES, 1, &maxSampleCount);
190e5c31af7Sopenharmony_ci
191e5c31af7Sopenharmony_ci		if (m_numRequestedSamples == SAMPLE_COUNT_MAX)
192e5c31af7Sopenharmony_ci			msaaTargetSamples = maxSampleCount;
193e5c31af7Sopenharmony_ci		else if (maxSampleCount >= m_numRequestedSamples)
194e5c31af7Sopenharmony_ci			msaaTargetSamples = m_numRequestedSamples;
195e5c31af7Sopenharmony_ci		else
196e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("Test requires " + de::toString(m_numRequestedSamples) + "x msaa rbo");
197e5c31af7Sopenharmony_ci	}
198e5c31af7Sopenharmony_ci
199e5c31af7Sopenharmony_ci	// Gen shader
200e5c31af7Sopenharmony_ci
201e5c31af7Sopenharmony_ci	{
202e5c31af7Sopenharmony_ci		tcu::StringTemplate					vertexSource	(s_shaderVertexTemplate);
203e5c31af7Sopenharmony_ci		tcu::StringTemplate					fragmentSource	(s_shaderFragmentTemplate);
204e5c31af7Sopenharmony_ci		std::map<std::string, std::string>	params;
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_ci		params["INTERPOLATION"] = (m_flatshade) ? ("flat ") : ("");
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_ci		m_shader = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vertexSource.specialize(params)) << glu::FragmentSource(fragmentSource.specialize(params)));
209e5c31af7Sopenharmony_ci		if (!m_shader->isOk())
210e5c31af7Sopenharmony_ci			throw tcu::TestError("could not create shader");
211e5c31af7Sopenharmony_ci	}
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_ci	// Fbo
214e5c31af7Sopenharmony_ci	if (m_renderTarget != RENDERTARGET_DEFAULT)
215e5c31af7Sopenharmony_ci	{
216e5c31af7Sopenharmony_ci		glw::GLenum error;
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci		gl.genFramebuffers(1, &m_fbo);
219e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci		switch (m_renderTarget)
222e5c31af7Sopenharmony_ci		{
223e5c31af7Sopenharmony_ci			case RENDERTARGET_TEXTURE_2D:
224e5c31af7Sopenharmony_ci			{
225e5c31af7Sopenharmony_ci				gl.genTextures(1, &m_texture);
226e5c31af7Sopenharmony_ci				gl.bindTexture(GL_TEXTURE_2D, m_texture);
227e5c31af7Sopenharmony_ci				gl.texStorage2D(GL_TEXTURE_2D, 1, m_fboInternalFormat, m_renderSize, m_renderSize);
228e5c31af7Sopenharmony_ci
229e5c31af7Sopenharmony_ci				error = gl.getError();
230e5c31af7Sopenharmony_ci				if (error == GL_OUT_OF_MEMORY)
231e5c31af7Sopenharmony_ci					throw tcu::NotSupportedError("could not create target texture, got out of memory");
232e5c31af7Sopenharmony_ci				else if (error != GL_NO_ERROR)
233e5c31af7Sopenharmony_ci					throw tcu::TestError("got " + de::toString(glu::getErrorStr(error)));
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ci				gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
236e5c31af7Sopenharmony_ci				break;
237e5c31af7Sopenharmony_ci			}
238e5c31af7Sopenharmony_ci
239e5c31af7Sopenharmony_ci			case RENDERTARGET_RBO_SINGLESAMPLE:
240e5c31af7Sopenharmony_ci			case RENDERTARGET_RBO_MULTISAMPLE:
241e5c31af7Sopenharmony_ci			{
242e5c31af7Sopenharmony_ci				gl.genRenderbuffers(1, &m_rbo);
243e5c31af7Sopenharmony_ci				gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci				if (m_renderTarget == RENDERTARGET_RBO_SINGLESAMPLE)
246e5c31af7Sopenharmony_ci					gl.renderbufferStorage(GL_RENDERBUFFER, m_fboInternalFormat, m_renderSize, m_renderSize);
247e5c31af7Sopenharmony_ci				else if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
248e5c31af7Sopenharmony_ci					gl.renderbufferStorageMultisample(GL_RENDERBUFFER, msaaTargetSamples, m_fboInternalFormat, m_renderSize, m_renderSize);
249e5c31af7Sopenharmony_ci				else
250e5c31af7Sopenharmony_ci					DE_ASSERT(false);
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci				error = gl.getError();
253e5c31af7Sopenharmony_ci				if (error == GL_OUT_OF_MEMORY)
254e5c31af7Sopenharmony_ci					throw tcu::NotSupportedError("could not create target texture, got out of memory");
255e5c31af7Sopenharmony_ci				else if (error != GL_NO_ERROR)
256e5c31af7Sopenharmony_ci					throw tcu::TestError("got " + de::toString(glu::getErrorStr(error)));
257e5c31af7Sopenharmony_ci
258e5c31af7Sopenharmony_ci				gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
259e5c31af7Sopenharmony_ci				break;
260e5c31af7Sopenharmony_ci			}
261e5c31af7Sopenharmony_ci
262e5c31af7Sopenharmony_ci			default:
263e5c31af7Sopenharmony_ci				DE_ASSERT(false);
264e5c31af7Sopenharmony_ci		}
265e5c31af7Sopenharmony_ci	}
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_ci	// Resolve (blitFramebuffer) target fbo for MSAA targets
268e5c31af7Sopenharmony_ci	if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
269e5c31af7Sopenharmony_ci	{
270e5c31af7Sopenharmony_ci		glw::GLenum error;
271e5c31af7Sopenharmony_ci
272e5c31af7Sopenharmony_ci		gl.genFramebuffers(1, &m_blitDstFbo);
273e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_FRAMEBUFFER, m_blitDstFbo);
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_ci		gl.genRenderbuffers(1, &m_blitDstRbo);
276e5c31af7Sopenharmony_ci		gl.bindRenderbuffer(GL_RENDERBUFFER, m_blitDstRbo);
277e5c31af7Sopenharmony_ci		gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, m_renderSize, m_renderSize);
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci		error = gl.getError();
280e5c31af7Sopenharmony_ci		if (error == GL_OUT_OF_MEMORY)
281e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("could not create blit target, got out of memory");
282e5c31af7Sopenharmony_ci		else if (error != GL_NO_ERROR)
283e5c31af7Sopenharmony_ci			throw tcu::TestError("got " + de::toString(glu::getErrorStr(error)));
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_blitDstRbo);
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_ci		// restore state
288e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
289e5c31af7Sopenharmony_ci	}
290e5c31af7Sopenharmony_ci
291e5c31af7Sopenharmony_ci	// Query info
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_ci	if (m_renderTarget == RENDERTARGET_DEFAULT)
294e5c31af7Sopenharmony_ci		m_numSamples = m_context.getRenderTarget().getNumSamples();
295e5c31af7Sopenharmony_ci	else if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
296e5c31af7Sopenharmony_ci	{
297e5c31af7Sopenharmony_ci		m_numSamples = -1;
298e5c31af7Sopenharmony_ci		gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
299e5c31af7Sopenharmony_ci		gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &m_numSamples);
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "get RENDERBUFFER_SAMPLES");
302e5c31af7Sopenharmony_ci	}
303e5c31af7Sopenharmony_ci	else
304e5c31af7Sopenharmony_ci		m_numSamples = 0;
305e5c31af7Sopenharmony_ci
306e5c31af7Sopenharmony_ci	gl.getIntegerv(GL_SUBPIXEL_BITS, &m_subpixelBits);
307e5c31af7Sopenharmony_ci
308e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Sample count = " << m_numSamples << tcu::TestLog::EndMessage;
309e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "SUBPIXEL_BITS = " << m_subpixelBits << tcu::TestLog::EndMessage;
310e5c31af7Sopenharmony_ci}
311e5c31af7Sopenharmony_ci
312e5c31af7Sopenharmony_civoid BaseRenderingCase::deinit (void)
313e5c31af7Sopenharmony_ci{
314e5c31af7Sopenharmony_ci	if (m_shader)
315e5c31af7Sopenharmony_ci	{
316e5c31af7Sopenharmony_ci		delete m_shader;
317e5c31af7Sopenharmony_ci		m_shader = DE_NULL;
318e5c31af7Sopenharmony_ci	}
319e5c31af7Sopenharmony_ci
320e5c31af7Sopenharmony_ci	if (m_fbo)
321e5c31af7Sopenharmony_ci	{
322e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_fbo);
323e5c31af7Sopenharmony_ci		m_fbo = 0;
324e5c31af7Sopenharmony_ci	}
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ci	if (m_rbo)
327e5c31af7Sopenharmony_ci	{
328e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_rbo);
329e5c31af7Sopenharmony_ci		m_rbo = 0;
330e5c31af7Sopenharmony_ci	}
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	if (m_texture)
333e5c31af7Sopenharmony_ci	{
334e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
335e5c31af7Sopenharmony_ci		m_texture = 0;
336e5c31af7Sopenharmony_ci	}
337e5c31af7Sopenharmony_ci
338e5c31af7Sopenharmony_ci	if (m_blitDstFbo)
339e5c31af7Sopenharmony_ci	{
340e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_blitDstFbo);
341e5c31af7Sopenharmony_ci		m_blitDstFbo = 0;
342e5c31af7Sopenharmony_ci	}
343e5c31af7Sopenharmony_ci
344e5c31af7Sopenharmony_ci	if (m_blitDstRbo)
345e5c31af7Sopenharmony_ci	{
346e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_blitDstRbo);
347e5c31af7Sopenharmony_ci		m_blitDstRbo = 0;
348e5c31af7Sopenharmony_ci	}
349e5c31af7Sopenharmony_ci}
350e5c31af7Sopenharmony_ci
351e5c31af7Sopenharmony_civoid BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, glw::GLenum primitiveType)
352e5c31af7Sopenharmony_ci{
353e5c31af7Sopenharmony_ci	// default to color white
354e5c31af7Sopenharmony_ci	const std::vector<tcu::Vec4> colorData(vertexData.size(), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ci	drawPrimitives(result, vertexData, colorData, primitiveType);
357e5c31af7Sopenharmony_ci}
358e5c31af7Sopenharmony_ci
359e5c31af7Sopenharmony_civoid BaseRenderingCase::drawPrimitives (tcu::Surface& result, const std::vector<tcu::Vec4>& vertexData, const std::vector<tcu::Vec4>& colorData, glw::GLenum primitiveType)
360e5c31af7Sopenharmony_ci{
361e5c31af7Sopenharmony_ci	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
362e5c31af7Sopenharmony_ci	const glw::GLint		positionLoc		= gl.getAttribLocation(m_shader->getProgram(), "a_position");
363e5c31af7Sopenharmony_ci	const glw::GLint		colorLoc		= gl.getAttribLocation(m_shader->getProgram(), "a_color");
364e5c31af7Sopenharmony_ci	const glw::GLint		pointSizeLoc	= gl.getUniformLocation(m_shader->getProgram(), "u_pointSize");
365e5c31af7Sopenharmony_ci
366e5c31af7Sopenharmony_ci	gl.clearColor					(0, 0, 0, 1);
367e5c31af7Sopenharmony_ci	gl.clear						(GL_COLOR_BUFFER_BIT);
368e5c31af7Sopenharmony_ci	gl.viewport						(0, 0, m_renderSize, m_renderSize);
369e5c31af7Sopenharmony_ci	gl.useProgram					(m_shader->getProgram());
370e5c31af7Sopenharmony_ci	gl.enableVertexAttribArray		(positionLoc);
371e5c31af7Sopenharmony_ci	gl.vertexAttribPointer			(positionLoc, 4, GL_FLOAT, GL_FALSE, 0, &vertexData[0]);
372e5c31af7Sopenharmony_ci	gl.enableVertexAttribArray		(colorLoc);
373e5c31af7Sopenharmony_ci	gl.vertexAttribPointer			(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, &colorData[0]);
374e5c31af7Sopenharmony_ci	gl.uniform1f					(pointSizeLoc, getPointSize());
375e5c31af7Sopenharmony_ci	gl.lineWidth					(getLineWidth());
376e5c31af7Sopenharmony_ci	gl.drawArrays					(primitiveType, 0, (glw::GLsizei)vertexData.size());
377e5c31af7Sopenharmony_ci	gl.disableVertexAttribArray		(colorLoc);
378e5c31af7Sopenharmony_ci	gl.disableVertexAttribArray		(positionLoc);
379e5c31af7Sopenharmony_ci	gl.useProgram					(0);
380e5c31af7Sopenharmony_ci	gl.finish						();
381e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR				(gl.getError(), "draw primitives");
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ci	// read pixels
384e5c31af7Sopenharmony_ci	if (m_renderTarget == RENDERTARGET_RBO_MULTISAMPLE)
385e5c31af7Sopenharmony_ci	{
386e5c31af7Sopenharmony_ci		// resolve msaa
387e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo);
388e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_blitDstFbo);
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_ci		gl.blitFramebuffer(0, 0, m_renderSize, m_renderSize, 0, 0, m_renderSize, m_renderSize, GL_COLOR_BUFFER_BIT, GL_NEAREST);
391e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "blit");
392e5c31af7Sopenharmony_ci
393e5c31af7Sopenharmony_ci		// read resolved
394e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_blitDstFbo);
395e5c31af7Sopenharmony_ci
396e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
397e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "read pixels");
398e5c31af7Sopenharmony_ci
399e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
400e5c31af7Sopenharmony_ci	}
401e5c31af7Sopenharmony_ci	else
402e5c31af7Sopenharmony_ci	{
403e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, result.getAccess());
404e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR				(gl.getError(), "read pixels");
405e5c31af7Sopenharmony_ci	}
406e5c31af7Sopenharmony_ci}
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_cifloat BaseRenderingCase::getLineWidth (void) const
409e5c31af7Sopenharmony_ci{
410e5c31af7Sopenharmony_ci	return 1.0f;
411e5c31af7Sopenharmony_ci}
412e5c31af7Sopenharmony_ci
413e5c31af7Sopenharmony_cifloat BaseRenderingCase::getPointSize (void) const
414e5c31af7Sopenharmony_ci{
415e5c31af7Sopenharmony_ci	return 1.0f;
416e5c31af7Sopenharmony_ci}
417e5c31af7Sopenharmony_ci
418e5c31af7Sopenharmony_ciconst tcu::PixelFormat& BaseRenderingCase::getPixelFormat (void) const
419e5c31af7Sopenharmony_ci{
420e5c31af7Sopenharmony_ci	return m_pixelFormat;
421e5c31af7Sopenharmony_ci}
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ciclass BaseTriangleCase : public BaseRenderingCase
424e5c31af7Sopenharmony_ci{
425e5c31af7Sopenharmony_cipublic:
426e5c31af7Sopenharmony_ci							BaseTriangleCase	(Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, BaseRenderingCase::RenderTarget renderTarget, int numSamples);
427e5c31af7Sopenharmony_ci							~BaseTriangleCase	(void);
428e5c31af7Sopenharmony_ci	IterateResult			iterate				(void);
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ciprivate:
431e5c31af7Sopenharmony_ci	virtual void			generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles) = DE_NULL;
432e5c31af7Sopenharmony_ci
433e5c31af7Sopenharmony_ci	int						m_iteration;
434e5c31af7Sopenharmony_ci	const int				m_iterationCount;
435e5c31af7Sopenharmony_ci	const glw::GLenum		m_primitiveDrawType;
436e5c31af7Sopenharmony_ci	bool					m_allIterationsPassed;
437e5c31af7Sopenharmony_ci};
438e5c31af7Sopenharmony_ci
439e5c31af7Sopenharmony_ciBaseTriangleCase::BaseTriangleCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
440e5c31af7Sopenharmony_ci	: BaseRenderingCase		(context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
441e5c31af7Sopenharmony_ci	, m_iteration			(0)
442e5c31af7Sopenharmony_ci	, m_iterationCount		(3)
443e5c31af7Sopenharmony_ci	, m_primitiveDrawType	(primitiveDrawType)
444e5c31af7Sopenharmony_ci	, m_allIterationsPassed	(true)
445e5c31af7Sopenharmony_ci{
446e5c31af7Sopenharmony_ci}
447e5c31af7Sopenharmony_ci
448e5c31af7Sopenharmony_ciBaseTriangleCase::~BaseTriangleCase (void)
449e5c31af7Sopenharmony_ci{
450e5c31af7Sopenharmony_ci}
451e5c31af7Sopenharmony_ci
452e5c31af7Sopenharmony_ciBaseTriangleCase::IterateResult BaseTriangleCase::iterate (void)
453e5c31af7Sopenharmony_ci{
454e5c31af7Sopenharmony_ci	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
455e5c31af7Sopenharmony_ci	const tcu::ScopedLogSection						section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
456e5c31af7Sopenharmony_ci	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
457e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>							drawBuffer;
458e5c31af7Sopenharmony_ci	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ci	generateTriangles(m_iteration, drawBuffer, triangles);
461e5c31af7Sopenharmony_ci
462e5c31af7Sopenharmony_ci	// draw image
463e5c31af7Sopenharmony_ci	drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
464e5c31af7Sopenharmony_ci
465e5c31af7Sopenharmony_ci	// compare
466e5c31af7Sopenharmony_ci	{
467e5c31af7Sopenharmony_ci		bool					compareOk;
468e5c31af7Sopenharmony_ci		RasterizationArguments	args;
469e5c31af7Sopenharmony_ci		TriangleSceneSpec		scene;
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ci		args.numSamples		= m_numSamples;
472e5c31af7Sopenharmony_ci		args.subpixelBits	= m_subpixelBits;
473e5c31af7Sopenharmony_ci		args.redBits		= getPixelFormat().redBits;
474e5c31af7Sopenharmony_ci		args.greenBits		= getPixelFormat().greenBits;
475e5c31af7Sopenharmony_ci		args.blueBits		= getPixelFormat().blueBits;
476e5c31af7Sopenharmony_ci
477e5c31af7Sopenharmony_ci		scene.triangles.swap(triangles);
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci		compareOk = verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci		if (!compareOk)
482e5c31af7Sopenharmony_ci			m_allIterationsPassed = false;
483e5c31af7Sopenharmony_ci	}
484e5c31af7Sopenharmony_ci
485e5c31af7Sopenharmony_ci	// result
486e5c31af7Sopenharmony_ci	if (++m_iteration == m_iterationCount)
487e5c31af7Sopenharmony_ci	{
488e5c31af7Sopenharmony_ci		if (m_allIterationsPassed)
489e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
490e5c31af7Sopenharmony_ci		else
491e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ci		return STOP;
494e5c31af7Sopenharmony_ci	}
495e5c31af7Sopenharmony_ci	else
496e5c31af7Sopenharmony_ci		return CONTINUE;
497e5c31af7Sopenharmony_ci}
498e5c31af7Sopenharmony_ci
499e5c31af7Sopenharmony_ciclass BaseLineCase : public BaseRenderingCase
500e5c31af7Sopenharmony_ci{
501e5c31af7Sopenharmony_cipublic:
502e5c31af7Sopenharmony_ci							BaseLineCase		(Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples);
503e5c31af7Sopenharmony_ci							~BaseLineCase		(void);
504e5c31af7Sopenharmony_ci
505e5c31af7Sopenharmony_ci	void					init				(void);
506e5c31af7Sopenharmony_ci	IterateResult			iterate				(void);
507e5c31af7Sopenharmony_ci	float					getLineWidth		(void) const;
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_ciprivate:
510e5c31af7Sopenharmony_ci	virtual void			generateLines		(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines) = DE_NULL;
511e5c31af7Sopenharmony_ci
512e5c31af7Sopenharmony_ci	int						m_iteration;
513e5c31af7Sopenharmony_ci	const int				m_iterationCount;
514e5c31af7Sopenharmony_ci	const glw::GLenum		m_primitiveDrawType;
515e5c31af7Sopenharmony_ci	const PrimitiveWideness	m_primitiveWideness;
516e5c31af7Sopenharmony_ci	bool					m_allIterationsPassed;
517e5c31af7Sopenharmony_ci	bool					m_multisampleRelaxationRequired;
518e5c31af7Sopenharmony_ci	float					m_maxLineWidth;
519e5c31af7Sopenharmony_ci	std::vector<float>		m_lineWidths;
520e5c31af7Sopenharmony_ci};
521e5c31af7Sopenharmony_ci
522e5c31af7Sopenharmony_ciBaseLineCase::BaseLineCase (Context& context, const char* name, const char* desc, glw::GLenum primitiveDrawType, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
523e5c31af7Sopenharmony_ci	: BaseRenderingCase					(context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
524e5c31af7Sopenharmony_ci	, m_iteration						(0)
525e5c31af7Sopenharmony_ci	, m_iterationCount					(3)
526e5c31af7Sopenharmony_ci	, m_primitiveDrawType				(primitiveDrawType)
527e5c31af7Sopenharmony_ci	, m_primitiveWideness				(wideness)
528e5c31af7Sopenharmony_ci	, m_allIterationsPassed				(true)
529e5c31af7Sopenharmony_ci	, m_multisampleRelaxationRequired	(false)
530e5c31af7Sopenharmony_ci	, m_maxLineWidth					(1.0f)
531e5c31af7Sopenharmony_ci{
532e5c31af7Sopenharmony_ci	DE_ASSERT(m_primitiveWideness < PRIMITIVEWIDENESS_LAST);
533e5c31af7Sopenharmony_ci}
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ciBaseLineCase::~BaseLineCase (void)
536e5c31af7Sopenharmony_ci{
537e5c31af7Sopenharmony_ci}
538e5c31af7Sopenharmony_ci
539e5c31af7Sopenharmony_civoid BaseLineCase::init (void)
540e5c31af7Sopenharmony_ci{
541e5c31af7Sopenharmony_ci	// create line widths
542e5c31af7Sopenharmony_ci	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
543e5c31af7Sopenharmony_ci	{
544e5c31af7Sopenharmony_ci		m_lineWidths.resize(m_iterationCount, 1.0f);
545e5c31af7Sopenharmony_ci	}
546e5c31af7Sopenharmony_ci	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
547e5c31af7Sopenharmony_ci	{
548e5c31af7Sopenharmony_ci		float range[2] = { 0.0f, 0.0f };
549e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
550e5c31af7Sopenharmony_ci
551e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci		// no wide line support
554e5c31af7Sopenharmony_ci		if (range[1] <= 1.0f)
555e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("wide line support required");
556e5c31af7Sopenharmony_ci
557e5c31af7Sopenharmony_ci		// set hand picked sizes
558e5c31af7Sopenharmony_ci		m_lineWidths.push_back(5.0f);
559e5c31af7Sopenharmony_ci		m_lineWidths.push_back(10.0f);
560e5c31af7Sopenharmony_ci		m_lineWidths.push_back(range[1]);
561e5c31af7Sopenharmony_ci		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
562e5c31af7Sopenharmony_ci
563e5c31af7Sopenharmony_ci		m_maxLineWidth = range[1];
564e5c31af7Sopenharmony_ci	}
565e5c31af7Sopenharmony_ci	else
566e5c31af7Sopenharmony_ci		DE_ASSERT(false);
567e5c31af7Sopenharmony_ci
568e5c31af7Sopenharmony_ci	// init parent
569e5c31af7Sopenharmony_ci	BaseRenderingCase::init();
570e5c31af7Sopenharmony_ci}
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ciBaseLineCase::IterateResult BaseLineCase::iterate (void)
573e5c31af7Sopenharmony_ci{
574e5c31af7Sopenharmony_ci	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
575e5c31af7Sopenharmony_ci	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
576e5c31af7Sopenharmony_ci	const float								lineWidth				= getLineWidth();
577e5c31af7Sopenharmony_ci	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
578e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>					drawBuffer;
579e5c31af7Sopenharmony_ci	std::vector<LineSceneSpec::SceneLine>	lines;
580e5c31af7Sopenharmony_ci
581e5c31af7Sopenharmony_ci	// supported?
582e5c31af7Sopenharmony_ci	if (lineWidth <= m_maxLineWidth)
583e5c31af7Sopenharmony_ci	{
584e5c31af7Sopenharmony_ci		// gen data
585e5c31af7Sopenharmony_ci		generateLines(m_iteration, drawBuffer, lines);
586e5c31af7Sopenharmony_ci
587e5c31af7Sopenharmony_ci		// draw image
588e5c31af7Sopenharmony_ci		drawPrimitives(resultImage, drawBuffer, m_primitiveDrawType);
589e5c31af7Sopenharmony_ci
590e5c31af7Sopenharmony_ci		// compare
591e5c31af7Sopenharmony_ci		{
592e5c31af7Sopenharmony_ci			bool					compareOk;
593e5c31af7Sopenharmony_ci			RasterizationArguments	args;
594e5c31af7Sopenharmony_ci			LineSceneSpec			scene;
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_ci			args.numSamples		= m_numSamples;
597e5c31af7Sopenharmony_ci			args.subpixelBits	= m_subpixelBits;
598e5c31af7Sopenharmony_ci			args.redBits		= getPixelFormat().redBits;
599e5c31af7Sopenharmony_ci			args.greenBits		= getPixelFormat().greenBits;
600e5c31af7Sopenharmony_ci			args.blueBits		= getPixelFormat().blueBits;
601e5c31af7Sopenharmony_ci
602e5c31af7Sopenharmony_ci			scene.lines.swap(lines);
603e5c31af7Sopenharmony_ci			scene.lineWidth = lineWidth;
604e5c31af7Sopenharmony_ci			scene.stippleFactor = 1;
605e5c31af7Sopenharmony_ci			scene.stipplePattern = 0xFFFF;
606e5c31af7Sopenharmony_ci			scene.allowNonProjectedInterpolation = true;
607e5c31af7Sopenharmony_ci
608e5c31af7Sopenharmony_ci			compareOk = verifyLineGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ci			// multisampled wide lines might not be supported
611e5c31af7Sopenharmony_ci			if (scene.lineWidth != 1.0f && m_numSamples > 1 && !compareOk)
612e5c31af7Sopenharmony_ci			{
613e5c31af7Sopenharmony_ci				m_multisampleRelaxationRequired = true;
614e5c31af7Sopenharmony_ci				compareOk = true;
615e5c31af7Sopenharmony_ci			}
616e5c31af7Sopenharmony_ci
617e5c31af7Sopenharmony_ci			if (!compareOk)
618e5c31af7Sopenharmony_ci				m_allIterationsPassed = false;
619e5c31af7Sopenharmony_ci		}
620e5c31af7Sopenharmony_ci	}
621e5c31af7Sopenharmony_ci	else
622e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci	// result
625e5c31af7Sopenharmony_ci	if (++m_iteration == m_iterationCount)
626e5c31af7Sopenharmony_ci	{
627e5c31af7Sopenharmony_ci		if (m_allIterationsPassed && m_multisampleRelaxationRequired)
628e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Rasterization of multisampled wide lines failed");
629e5c31af7Sopenharmony_ci		else if (m_allIterationsPassed)
630e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
631e5c31af7Sopenharmony_ci		else
632e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
633e5c31af7Sopenharmony_ci
634e5c31af7Sopenharmony_ci		return STOP;
635e5c31af7Sopenharmony_ci	}
636e5c31af7Sopenharmony_ci	else
637e5c31af7Sopenharmony_ci		return CONTINUE;
638e5c31af7Sopenharmony_ci}
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_cifloat BaseLineCase::getLineWidth (void) const
641e5c31af7Sopenharmony_ci{
642e5c31af7Sopenharmony_ci	return m_lineWidths[m_iteration];
643e5c31af7Sopenharmony_ci}
644e5c31af7Sopenharmony_ci
645e5c31af7Sopenharmony_ciclass PointCase : public BaseRenderingCase
646e5c31af7Sopenharmony_ci{
647e5c31af7Sopenharmony_cipublic:
648e5c31af7Sopenharmony_ci							PointCase		(Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
649e5c31af7Sopenharmony_ci							~PointCase		(void);
650e5c31af7Sopenharmony_ci
651e5c31af7Sopenharmony_ci	void					init			(void);
652e5c31af7Sopenharmony_ci	IterateResult			iterate			(void);
653e5c31af7Sopenharmony_ci
654e5c31af7Sopenharmony_ciprotected:
655e5c31af7Sopenharmony_ci	float					getPointSize	(void) const;
656e5c31af7Sopenharmony_ci
657e5c31af7Sopenharmony_ciprivate:
658e5c31af7Sopenharmony_ci	void					generatePoints	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints);
659e5c31af7Sopenharmony_ci
660e5c31af7Sopenharmony_ci	int						m_iteration;
661e5c31af7Sopenharmony_ci	const int				m_iterationCount;
662e5c31af7Sopenharmony_ci	const PrimitiveWideness	m_primitiveWideness;
663e5c31af7Sopenharmony_ci	bool					m_allIterationsPassed;
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_ci	float					m_maxPointSize;
666e5c31af7Sopenharmony_ci	std::vector<float>		m_pointSizes;
667e5c31af7Sopenharmony_ci};
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_ciPointCase::PointCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
670e5c31af7Sopenharmony_ci	: BaseRenderingCase		(context, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
671e5c31af7Sopenharmony_ci	, m_iteration			(0)
672e5c31af7Sopenharmony_ci	, m_iterationCount		(3)
673e5c31af7Sopenharmony_ci	, m_primitiveWideness	(wideness)
674e5c31af7Sopenharmony_ci	, m_allIterationsPassed	(true)
675e5c31af7Sopenharmony_ci	, m_maxPointSize		(1.0f)
676e5c31af7Sopenharmony_ci{
677e5c31af7Sopenharmony_ci}
678e5c31af7Sopenharmony_ci
679e5c31af7Sopenharmony_ciPointCase::~PointCase (void)
680e5c31af7Sopenharmony_ci{
681e5c31af7Sopenharmony_ci}
682e5c31af7Sopenharmony_ci
683e5c31af7Sopenharmony_civoid PointCase::init (void)
684e5c31af7Sopenharmony_ci{
685e5c31af7Sopenharmony_ci	// create point sizes
686e5c31af7Sopenharmony_ci	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
687e5c31af7Sopenharmony_ci	{
688e5c31af7Sopenharmony_ci		m_pointSizes.resize(m_iterationCount, 1.0f);
689e5c31af7Sopenharmony_ci	}
690e5c31af7Sopenharmony_ci	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
691e5c31af7Sopenharmony_ci	{
692e5c31af7Sopenharmony_ci		float range[2] = { 0.0f, 0.0f };
693e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_POINT_SIZE_RANGE, range);
694e5c31af7Sopenharmony_ci
695e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "GL_ALIASED_POINT_SIZE_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci		// no wide line support
698e5c31af7Sopenharmony_ci		if (range[1] <= 1.0f)
699e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("wide point support required");
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_ci		// set hand picked sizes
702e5c31af7Sopenharmony_ci		m_pointSizes.push_back(10.0f);
703e5c31af7Sopenharmony_ci		m_pointSizes.push_back(25.0f);
704e5c31af7Sopenharmony_ci		m_pointSizes.push_back(range[1]);
705e5c31af7Sopenharmony_ci		DE_ASSERT((int)m_pointSizes.size() == m_iterationCount);
706e5c31af7Sopenharmony_ci
707e5c31af7Sopenharmony_ci		m_maxPointSize = range[1];
708e5c31af7Sopenharmony_ci	}
709e5c31af7Sopenharmony_ci	else
710e5c31af7Sopenharmony_ci		DE_ASSERT(false);
711e5c31af7Sopenharmony_ci
712e5c31af7Sopenharmony_ci	// init parent
713e5c31af7Sopenharmony_ci	BaseRenderingCase::init();
714e5c31af7Sopenharmony_ci}
715e5c31af7Sopenharmony_ci
716e5c31af7Sopenharmony_ciPointCase::IterateResult PointCase::iterate (void)
717e5c31af7Sopenharmony_ci{
718e5c31af7Sopenharmony_ci	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
719e5c31af7Sopenharmony_ci	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
720e5c31af7Sopenharmony_ci	const float								pointSize				= getPointSize();
721e5c31af7Sopenharmony_ci	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
722e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>					drawBuffer;
723e5c31af7Sopenharmony_ci	std::vector<PointSceneSpec::ScenePoint>	points;
724e5c31af7Sopenharmony_ci
725e5c31af7Sopenharmony_ci	// supported?
726e5c31af7Sopenharmony_ci	if (pointSize <= m_maxPointSize)
727e5c31af7Sopenharmony_ci	{
728e5c31af7Sopenharmony_ci		// gen data
729e5c31af7Sopenharmony_ci		generatePoints(m_iteration, drawBuffer, points);
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci		// draw image
732e5c31af7Sopenharmony_ci		drawPrimitives(resultImage, drawBuffer, GL_POINTS);
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_ci		// compare
735e5c31af7Sopenharmony_ci		{
736e5c31af7Sopenharmony_ci			bool					compareOk;
737e5c31af7Sopenharmony_ci			RasterizationArguments	args;
738e5c31af7Sopenharmony_ci			PointSceneSpec			scene;
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ci			args.numSamples		= m_numSamples;
741e5c31af7Sopenharmony_ci			args.subpixelBits	= m_subpixelBits;
742e5c31af7Sopenharmony_ci			args.redBits		= getPixelFormat().redBits;
743e5c31af7Sopenharmony_ci			args.greenBits		= getPixelFormat().greenBits;
744e5c31af7Sopenharmony_ci			args.blueBits		= getPixelFormat().blueBits;
745e5c31af7Sopenharmony_ci
746e5c31af7Sopenharmony_ci			scene.points.swap(points);
747e5c31af7Sopenharmony_ci
748e5c31af7Sopenharmony_ci			compareOk = verifyPointGroupRasterization(resultImage, scene, args, m_testCtx.getLog());
749e5c31af7Sopenharmony_ci
750e5c31af7Sopenharmony_ci			if (!compareOk)
751e5c31af7Sopenharmony_ci				m_allIterationsPassed = false;
752e5c31af7Sopenharmony_ci		}
753e5c31af7Sopenharmony_ci	}
754e5c31af7Sopenharmony_ci	else
755e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Point size " << pointSize << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci	// result
758e5c31af7Sopenharmony_ci	if (++m_iteration == m_iterationCount)
759e5c31af7Sopenharmony_ci	{
760e5c31af7Sopenharmony_ci		if (m_allIterationsPassed)
761e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
762e5c31af7Sopenharmony_ci		else
763e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rasterization");
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci		return STOP;
766e5c31af7Sopenharmony_ci	}
767e5c31af7Sopenharmony_ci	else
768e5c31af7Sopenharmony_ci		return CONTINUE;
769e5c31af7Sopenharmony_ci}
770e5c31af7Sopenharmony_ci
771e5c31af7Sopenharmony_cifloat PointCase::getPointSize (void) const
772e5c31af7Sopenharmony_ci{
773e5c31af7Sopenharmony_ci	return m_pointSizes[m_iteration];
774e5c31af7Sopenharmony_ci}
775e5c31af7Sopenharmony_ci
776e5c31af7Sopenharmony_civoid PointCase::generatePoints (int iteration, std::vector<tcu::Vec4>& outData, std::vector<PointSceneSpec::ScenePoint>& outPoints)
777e5c31af7Sopenharmony_ci{
778e5c31af7Sopenharmony_ci	outData.resize(6);
779e5c31af7Sopenharmony_ci
780e5c31af7Sopenharmony_ci	switch (iteration)
781e5c31af7Sopenharmony_ci	{
782e5c31af7Sopenharmony_ci		case 0:
783e5c31af7Sopenharmony_ci			// \note: these values are chosen arbitrarily
784e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
785e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
786e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
787e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
788e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(-0.2f, -0.4f, 0.0f, 1.0f);
789e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
790e5c31af7Sopenharmony_ci			break;
791e5c31af7Sopenharmony_ci
792e5c31af7Sopenharmony_ci		case 1:
793e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
794e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
795e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
796e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
797e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
798e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
799e5c31af7Sopenharmony_ci			break;
800e5c31af7Sopenharmony_ci
801e5c31af7Sopenharmony_ci		case 2:
802e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
803e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(  0.3f, -0.9f, 0.0f, 1.0f);
804e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( -0.4f, -0.1f, 0.0f, 1.0f);
805e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
806e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
807e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
808e5c31af7Sopenharmony_ci			break;
809e5c31af7Sopenharmony_ci	}
810e5c31af7Sopenharmony_ci
811e5c31af7Sopenharmony_ci	outPoints.resize(outData.size());
812e5c31af7Sopenharmony_ci	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
813e5c31af7Sopenharmony_ci	{
814e5c31af7Sopenharmony_ci		outPoints[pointNdx].position = outData[pointNdx];
815e5c31af7Sopenharmony_ci		outPoints[pointNdx].pointSize = getPointSize();
816e5c31af7Sopenharmony_ci	}
817e5c31af7Sopenharmony_ci
818e5c31af7Sopenharmony_ci	// log
819e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outPoints.size() << " point(s): (point size = " << getPointSize() << ")" << tcu::TestLog::EndMessage;
820e5c31af7Sopenharmony_ci	for (int pointNdx = 0; pointNdx < (int)outPoints.size(); ++pointNdx)
821e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Point " << (pointNdx+1) << ":\t" << outPoints[pointNdx].position << tcu::TestLog::EndMessage;
822e5c31af7Sopenharmony_ci}
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ciclass TrianglesCase : public BaseTriangleCase
825e5c31af7Sopenharmony_ci{
826e5c31af7Sopenharmony_cipublic:
827e5c31af7Sopenharmony_ci	TrianglesCase		(Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
828e5c31af7Sopenharmony_ci	~TrianglesCase		(void);
829e5c31af7Sopenharmony_ci
830e5c31af7Sopenharmony_ci	void	generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
831e5c31af7Sopenharmony_ci};
832e5c31af7Sopenharmony_ci
833e5c31af7Sopenharmony_ciTrianglesCase::TrianglesCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
834e5c31af7Sopenharmony_ci	: BaseTriangleCase(context, name, desc, GL_TRIANGLES, renderTarget, numSamples)
835e5c31af7Sopenharmony_ci{
836e5c31af7Sopenharmony_ci}
837e5c31af7Sopenharmony_ci
838e5c31af7Sopenharmony_ciTrianglesCase::~TrianglesCase (void)
839e5c31af7Sopenharmony_ci{
840e5c31af7Sopenharmony_ci
841e5c31af7Sopenharmony_ci}
842e5c31af7Sopenharmony_ci
843e5c31af7Sopenharmony_civoid TrianglesCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
844e5c31af7Sopenharmony_ci{
845e5c31af7Sopenharmony_ci	outData.resize(6);
846e5c31af7Sopenharmony_ci
847e5c31af7Sopenharmony_ci	switch (iteration)
848e5c31af7Sopenharmony_ci	{
849e5c31af7Sopenharmony_ci		case 0:
850e5c31af7Sopenharmony_ci			// \note: these values are chosen arbitrarily
851e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( 0.2f,  0.8f, 0.0f, 1.0f);
852e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4( 0.5f,  0.2f, 0.0f, 1.0f);
853e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( 0.5f,  0.3f, 0.0f, 1.0f);
854e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.5f,  0.2f, 0.0f, 1.0f);
855e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(-1.5f, -0.4f, 0.0f, 1.0f);
856e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4(-0.4f,  0.2f, 0.0f, 1.0f);
857e5c31af7Sopenharmony_ci			break;
858e5c31af7Sopenharmony_ci
859e5c31af7Sopenharmony_ci		case 1:
860e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
861e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
862e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
863e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
864e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
865e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4(   0.4f,   1.2f, 0.0f, 1.0f);
866e5c31af7Sopenharmony_ci			break;
867e5c31af7Sopenharmony_ci
868e5c31af7Sopenharmony_ci		case 2:
869e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
870e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
871e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( -1.1f, -0.1f, 0.0f, 1.0f);
872e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.11f,  0.2f, 0.0f, 1.0f);
873e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
874e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4( -0.4f,  0.4f, 0.0f, 1.0f);
875e5c31af7Sopenharmony_ci			break;
876e5c31af7Sopenharmony_ci	}
877e5c31af7Sopenharmony_ci
878e5c31af7Sopenharmony_ci	outTriangles.resize(2);
879e5c31af7Sopenharmony_ci	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
880e5c31af7Sopenharmony_ci	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
881e5c31af7Sopenharmony_ci	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
882e5c31af7Sopenharmony_ci
883e5c31af7Sopenharmony_ci	outTriangles[1].positions[0] = outData[3];	outTriangles[1].sharedEdge[0] = false;
884e5c31af7Sopenharmony_ci	outTriangles[1].positions[1] = outData[4];	outTriangles[1].sharedEdge[1] = false;
885e5c31af7Sopenharmony_ci	outTriangles[1].positions[2] = outData[5];	outTriangles[1].sharedEdge[2] = false;
886e5c31af7Sopenharmony_ci
887e5c31af7Sopenharmony_ci	// log
888e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outTriangles.size() << " triangle(s):" << tcu::TestLog::EndMessage;
889e5c31af7Sopenharmony_ci	for (int triangleNdx = 0; triangleNdx < (int)outTriangles.size(); ++triangleNdx)
890e5c31af7Sopenharmony_ci	{
891e5c31af7Sopenharmony_ci		m_testCtx.getLog()
892e5c31af7Sopenharmony_ci			<< tcu::TestLog::Message
893e5c31af7Sopenharmony_ci			<< "Triangle " << (triangleNdx+1) << ":"
894e5c31af7Sopenharmony_ci			<< "\n\t" << outTriangles[triangleNdx].positions[0]
895e5c31af7Sopenharmony_ci			<< "\n\t" << outTriangles[triangleNdx].positions[1]
896e5c31af7Sopenharmony_ci			<< "\n\t" << outTriangles[triangleNdx].positions[2]
897e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
898e5c31af7Sopenharmony_ci	}
899e5c31af7Sopenharmony_ci}
900e5c31af7Sopenharmony_ci
901e5c31af7Sopenharmony_ciclass TriangleStripCase : public BaseTriangleCase
902e5c31af7Sopenharmony_ci{
903e5c31af7Sopenharmony_cipublic:
904e5c31af7Sopenharmony_ci			TriangleStripCase	(Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
905e5c31af7Sopenharmony_ci
906e5c31af7Sopenharmony_ci	void	generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
907e5c31af7Sopenharmony_ci};
908e5c31af7Sopenharmony_ci
909e5c31af7Sopenharmony_ciTriangleStripCase::TriangleStripCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
910e5c31af7Sopenharmony_ci	: BaseTriangleCase(context, name, desc, GL_TRIANGLE_STRIP, renderTarget, numSamples)
911e5c31af7Sopenharmony_ci{
912e5c31af7Sopenharmony_ci}
913e5c31af7Sopenharmony_ci
914e5c31af7Sopenharmony_civoid TriangleStripCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
915e5c31af7Sopenharmony_ci{
916e5c31af7Sopenharmony_ci	outData.resize(5);
917e5c31af7Sopenharmony_ci
918e5c31af7Sopenharmony_ci	switch (iteration)
919e5c31af7Sopenharmony_ci	{
920e5c31af7Sopenharmony_ci		case 0:
921e5c31af7Sopenharmony_ci			// \note: these values are chosen arbitrarily
922e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.504f,  0.8f,   0.0f, 1.0f);
923e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.2f,   -0.2f,   0.0f, 1.0f);
924e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(-0.2f,    0.199f, 0.0f, 1.0f);
925e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4( 0.5f,    0.201f, 0.0f, 1.0f);
926e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4( 1.5f,    0.4f,   0.0f, 1.0f);
927e5c31af7Sopenharmony_ci			break;
928e5c31af7Sopenharmony_ci
929e5c31af7Sopenharmony_ci		case 1:
930e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.499f, 0.129f,  0.0f, 1.0f);
931e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.501f,  -0.3f,  0.0f, 1.0f);
932e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.11f,  -0.2f,  0.0f, 1.0f);
933e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(  0.11f,  -0.31f, 0.0f, 1.0f);
934e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(  0.88f,   0.9f,  0.0f, 1.0f);
935e5c31af7Sopenharmony_ci			break;
936e5c31af7Sopenharmony_ci
937e5c31af7Sopenharmony_ci		case 2:
938e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( -0.9f, -0.3f,  0.0f, 1.0f);
939e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(  1.1f, -0.9f,  0.0f, 1.0f);
940e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(-0.87f, -0.1f,  0.0f, 1.0f);
941e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.11f,  0.19f, 0.0f, 1.0f);
942e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4( 0.88f,  0.7f,  0.0f, 1.0f);
943e5c31af7Sopenharmony_ci			break;
944e5c31af7Sopenharmony_ci	}
945e5c31af7Sopenharmony_ci
946e5c31af7Sopenharmony_ci	outTriangles.resize(3);
947e5c31af7Sopenharmony_ci	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
948e5c31af7Sopenharmony_ci	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = true;
949e5c31af7Sopenharmony_ci	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = false;
950e5c31af7Sopenharmony_ci
951e5c31af7Sopenharmony_ci	outTriangles[1].positions[0] = outData[2];	outTriangles[1].sharedEdge[0] = true;
952e5c31af7Sopenharmony_ci	outTriangles[1].positions[1] = outData[1];	outTriangles[1].sharedEdge[1] = false;
953e5c31af7Sopenharmony_ci	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
954e5c31af7Sopenharmony_ci
955e5c31af7Sopenharmony_ci	outTriangles[2].positions[0] = outData[2];	outTriangles[2].sharedEdge[0] = true;
956e5c31af7Sopenharmony_ci	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
957e5c31af7Sopenharmony_ci	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
958e5c31af7Sopenharmony_ci
959e5c31af7Sopenharmony_ci	// log
960e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle strip, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
961e5c31af7Sopenharmony_ci	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
962e5c31af7Sopenharmony_ci	{
963e5c31af7Sopenharmony_ci		m_testCtx.getLog()
964e5c31af7Sopenharmony_ci			<< tcu::TestLog::Message
965e5c31af7Sopenharmony_ci			<< "\t" << outData[vtxNdx]
966e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
967e5c31af7Sopenharmony_ci	}
968e5c31af7Sopenharmony_ci}
969e5c31af7Sopenharmony_ci
970e5c31af7Sopenharmony_ciclass TriangleFanCase : public BaseTriangleCase
971e5c31af7Sopenharmony_ci{
972e5c31af7Sopenharmony_cipublic:
973e5c31af7Sopenharmony_ci			TriangleFanCase		(Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
974e5c31af7Sopenharmony_ci
975e5c31af7Sopenharmony_ci	void	generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles);
976e5c31af7Sopenharmony_ci};
977e5c31af7Sopenharmony_ci
978e5c31af7Sopenharmony_ciTriangleFanCase::TriangleFanCase (Context& context, const char* name, const char* desc, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
979e5c31af7Sopenharmony_ci	: BaseTriangleCase(context, name, desc, GL_TRIANGLE_FAN, renderTarget, numSamples)
980e5c31af7Sopenharmony_ci{
981e5c31af7Sopenharmony_ci}
982e5c31af7Sopenharmony_ci
983e5c31af7Sopenharmony_civoid TriangleFanCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData, std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles)
984e5c31af7Sopenharmony_ci{
985e5c31af7Sopenharmony_ci	outData.resize(5);
986e5c31af7Sopenharmony_ci
987e5c31af7Sopenharmony_ci	switch (iteration)
988e5c31af7Sopenharmony_ci	{
989e5c31af7Sopenharmony_ci		case 0:
990e5c31af7Sopenharmony_ci			// \note: these values are chosen arbitrarily
991e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
992e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
993e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
994e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
995e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
996e5c31af7Sopenharmony_ci			break;
997e5c31af7Sopenharmony_ci
998e5c31af7Sopenharmony_ci		case 1:
999e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1000e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1001e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1002e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1003e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1004e5c31af7Sopenharmony_ci			break;
1005e5c31af7Sopenharmony_ci
1006e5c31af7Sopenharmony_ci		case 2:
1007e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1008e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1009e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1010e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1011e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1012e5c31af7Sopenharmony_ci			break;
1013e5c31af7Sopenharmony_ci	}
1014e5c31af7Sopenharmony_ci
1015e5c31af7Sopenharmony_ci	outTriangles.resize(3);
1016e5c31af7Sopenharmony_ci	outTriangles[0].positions[0] = outData[0];	outTriangles[0].sharedEdge[0] = false;
1017e5c31af7Sopenharmony_ci	outTriangles[0].positions[1] = outData[1];	outTriangles[0].sharedEdge[1] = false;
1018e5c31af7Sopenharmony_ci	outTriangles[0].positions[2] = outData[2];	outTriangles[0].sharedEdge[2] = true;
1019e5c31af7Sopenharmony_ci
1020e5c31af7Sopenharmony_ci	outTriangles[1].positions[0] = outData[0];	outTriangles[1].sharedEdge[0] = true;
1021e5c31af7Sopenharmony_ci	outTriangles[1].positions[1] = outData[2];	outTriangles[1].sharedEdge[1] = false;
1022e5c31af7Sopenharmony_ci	outTriangles[1].positions[2] = outData[3];	outTriangles[1].sharedEdge[2] = true;
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_ci	outTriangles[2].positions[0] = outData[0];	outTriangles[2].sharedEdge[0] = true;
1025e5c31af7Sopenharmony_ci	outTriangles[2].positions[1] = outData[3];	outTriangles[2].sharedEdge[1] = false;
1026e5c31af7Sopenharmony_ci	outTriangles[2].positions[2] = outData[4];	outTriangles[2].sharedEdge[2] = false;
1027e5c31af7Sopenharmony_ci
1028e5c31af7Sopenharmony_ci	// log
1029e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering triangle fan, " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1030e5c31af7Sopenharmony_ci	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1031e5c31af7Sopenharmony_ci	{
1032e5c31af7Sopenharmony_ci		m_testCtx.getLog()
1033e5c31af7Sopenharmony_ci			<< tcu::TestLog::Message
1034e5c31af7Sopenharmony_ci			<< "\t" << outData[vtxNdx]
1035e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1036e5c31af7Sopenharmony_ci	}
1037e5c31af7Sopenharmony_ci}
1038e5c31af7Sopenharmony_ci
1039e5c31af7Sopenharmony_ciclass LinesCase : public BaseLineCase
1040e5c31af7Sopenharmony_ci{
1041e5c31af7Sopenharmony_cipublic:
1042e5c31af7Sopenharmony_ci			LinesCase		(Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_ci	void	generateLines	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1045e5c31af7Sopenharmony_ci};
1046e5c31af7Sopenharmony_ci
1047e5c31af7Sopenharmony_ciLinesCase::LinesCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
1048e5c31af7Sopenharmony_ci	: BaseLineCase(context, name, desc, GL_LINES, wideness, renderTarget, numSamples)
1049e5c31af7Sopenharmony_ci{
1050e5c31af7Sopenharmony_ci}
1051e5c31af7Sopenharmony_ci
1052e5c31af7Sopenharmony_civoid LinesCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1053e5c31af7Sopenharmony_ci{
1054e5c31af7Sopenharmony_ci	outData.resize(6);
1055e5c31af7Sopenharmony_ci
1056e5c31af7Sopenharmony_ci	switch (iteration)
1057e5c31af7Sopenharmony_ci	{
1058e5c31af7Sopenharmony_ci		case 0:
1059e5c31af7Sopenharmony_ci			// \note: these values are chosen arbitrarily
1060e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1061e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1062e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1063e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.3f,   0.2f, 0.0f, 1.0f);
1064e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(-1.5f,  -0.4f, 0.0f, 1.0f);
1065e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4( 0.1f,   0.5f, 0.0f, 1.0f);
1066e5c31af7Sopenharmony_ci			break;
1067e5c31af7Sopenharmony_ci
1068e5c31af7Sopenharmony_ci		case 1:
1069e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1070e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1071e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1072e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1073e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(  0.88f,   0.9f, 0.0f, 1.0f);
1074e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4(  0.18f,  -0.2f, 0.0f, 1.0f);
1075e5c31af7Sopenharmony_ci			break;
1076e5c31af7Sopenharmony_ci
1077e5c31af7Sopenharmony_ci		case 2:
1078e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1079e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1080e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1081e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1082e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4( 0.88f,  0.7f, 0.0f, 1.0f);
1083e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4(  0.8f, -0.7f, 0.0f, 1.0f);
1084e5c31af7Sopenharmony_ci			break;
1085e5c31af7Sopenharmony_ci	}
1086e5c31af7Sopenharmony_ci
1087e5c31af7Sopenharmony_ci	outLines.resize(3);
1088e5c31af7Sopenharmony_ci	outLines[0].positions[0] = outData[0];
1089e5c31af7Sopenharmony_ci	outLines[0].positions[1] = outData[1];
1090e5c31af7Sopenharmony_ci	outLines[1].positions[0] = outData[2];
1091e5c31af7Sopenharmony_ci	outLines[1].positions[1] = outData[3];
1092e5c31af7Sopenharmony_ci	outLines[2].positions[0] = outData[4];
1093e5c31af7Sopenharmony_ci	outLines[2].positions[1] = outData[5];
1094e5c31af7Sopenharmony_ci
1095e5c31af7Sopenharmony_ci	// log
1096e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering " << outLines.size() << " lines(s): (width = " << getLineWidth() << ")" << tcu::TestLog::EndMessage;
1097e5c31af7Sopenharmony_ci	for (int lineNdx = 0; lineNdx < (int)outLines.size(); ++lineNdx)
1098e5c31af7Sopenharmony_ci	{
1099e5c31af7Sopenharmony_ci		m_testCtx.getLog()
1100e5c31af7Sopenharmony_ci			<< tcu::TestLog::Message
1101e5c31af7Sopenharmony_ci			<< "Line " << (lineNdx+1) << ":"
1102e5c31af7Sopenharmony_ci			<< "\n\t" << outLines[lineNdx].positions[0]
1103e5c31af7Sopenharmony_ci			<< "\n\t" << outLines[lineNdx].positions[1]
1104e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1105e5c31af7Sopenharmony_ci	}
1106e5c31af7Sopenharmony_ci}
1107e5c31af7Sopenharmony_ci
1108e5c31af7Sopenharmony_ciclass LineStripCase : public BaseLineCase
1109e5c31af7Sopenharmony_ci{
1110e5c31af7Sopenharmony_cipublic:
1111e5c31af7Sopenharmony_ci			LineStripCase	(Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1112e5c31af7Sopenharmony_ci
1113e5c31af7Sopenharmony_ci	void	generateLines	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1114e5c31af7Sopenharmony_ci};
1115e5c31af7Sopenharmony_ci
1116e5c31af7Sopenharmony_ciLineStripCase::LineStripCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
1117e5c31af7Sopenharmony_ci	: BaseLineCase(context, name, desc, GL_LINE_STRIP, wideness, renderTarget, numSamples)
1118e5c31af7Sopenharmony_ci{
1119e5c31af7Sopenharmony_ci}
1120e5c31af7Sopenharmony_ci
1121e5c31af7Sopenharmony_civoid LineStripCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1122e5c31af7Sopenharmony_ci{
1123e5c31af7Sopenharmony_ci	outData.resize(4);
1124e5c31af7Sopenharmony_ci
1125e5c31af7Sopenharmony_ci	switch (iteration)
1126e5c31af7Sopenharmony_ci	{
1127e5c31af7Sopenharmony_ci		case 0:
1128e5c31af7Sopenharmony_ci			// \note: these values are chosen arbitrarily
1129e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1130e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1131e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1132e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
1133e5c31af7Sopenharmony_ci			break;
1134e5c31af7Sopenharmony_ci
1135e5c31af7Sopenharmony_ci		case 1:
1136e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1137e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1138e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1139e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1140e5c31af7Sopenharmony_ci			break;
1141e5c31af7Sopenharmony_ci
1142e5c31af7Sopenharmony_ci		case 2:
1143e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1144e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1145e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1146e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1147e5c31af7Sopenharmony_ci			break;
1148e5c31af7Sopenharmony_ci	}
1149e5c31af7Sopenharmony_ci
1150e5c31af7Sopenharmony_ci	outLines.resize(3);
1151e5c31af7Sopenharmony_ci	outLines[0].positions[0] = outData[0];
1152e5c31af7Sopenharmony_ci	outLines[0].positions[1] = outData[1];
1153e5c31af7Sopenharmony_ci	outLines[1].positions[0] = outData[1];
1154e5c31af7Sopenharmony_ci	outLines[1].positions[1] = outData[2];
1155e5c31af7Sopenharmony_ci	outLines[2].positions[0] = outData[2];
1156e5c31af7Sopenharmony_ci	outLines[2].positions[1] = outData[3];
1157e5c31af7Sopenharmony_ci
1158e5c31af7Sopenharmony_ci	// log
1159e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line strip, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1160e5c31af7Sopenharmony_ci	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1161e5c31af7Sopenharmony_ci	{
1162e5c31af7Sopenharmony_ci		m_testCtx.getLog()
1163e5c31af7Sopenharmony_ci			<< tcu::TestLog::Message
1164e5c31af7Sopenharmony_ci			<< "\t" << outData[vtxNdx]
1165e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1166e5c31af7Sopenharmony_ci	}
1167e5c31af7Sopenharmony_ci}
1168e5c31af7Sopenharmony_ci
1169e5c31af7Sopenharmony_ciclass LineLoopCase : public BaseLineCase
1170e5c31af7Sopenharmony_ci{
1171e5c31af7Sopenharmony_cipublic:
1172e5c31af7Sopenharmony_ci			LineLoopCase	(Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1173e5c31af7Sopenharmony_ci
1174e5c31af7Sopenharmony_ci	void	generateLines	(int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines);
1175e5c31af7Sopenharmony_ci};
1176e5c31af7Sopenharmony_ci
1177e5c31af7Sopenharmony_ciLineLoopCase::LineLoopCase (Context& context, const char* name, const char* desc, PrimitiveWideness wideness, BaseRenderingCase::RenderTarget renderTarget, int numSamples)
1178e5c31af7Sopenharmony_ci	: BaseLineCase(context, name, desc, GL_LINE_LOOP, wideness, renderTarget, numSamples)
1179e5c31af7Sopenharmony_ci{
1180e5c31af7Sopenharmony_ci}
1181e5c31af7Sopenharmony_ci
1182e5c31af7Sopenharmony_civoid LineLoopCase::generateLines (int iteration, std::vector<tcu::Vec4>& outData, std::vector<LineSceneSpec::SceneLine>& outLines)
1183e5c31af7Sopenharmony_ci{
1184e5c31af7Sopenharmony_ci	outData.resize(4);
1185e5c31af7Sopenharmony_ci
1186e5c31af7Sopenharmony_ci	switch (iteration)
1187e5c31af7Sopenharmony_ci	{
1188e5c31af7Sopenharmony_ci		case 0:
1189e5c31af7Sopenharmony_ci			// \note: these values are chosen arbitrarily
1190e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( 0.01f,  0.0f, 0.0f, 1.0f);
1191e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4( 0.5f,   0.2f, 0.0f, 1.0f);
1192e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4( 0.46f,  0.3f, 0.0f, 1.0f);
1193e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(-0.5f,   0.2f, 0.0f, 1.0f);
1194e5c31af7Sopenharmony_ci			break;
1195e5c31af7Sopenharmony_ci
1196e5c31af7Sopenharmony_ci		case 1:
1197e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(-0.499f, 0.128f, 0.0f, 1.0f);
1198e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(-0.501f,  -0.3f, 0.0f, 1.0f);
1199e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.11f,  -0.2f, 0.0f, 1.0f);
1200e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(  0.11f,   0.2f, 0.0f, 1.0f);
1201e5c31af7Sopenharmony_ci			break;
1202e5c31af7Sopenharmony_ci
1203e5c31af7Sopenharmony_ci		case 2:
1204e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4( -0.9f, -0.3f, 0.0f, 1.0f);
1205e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(  1.1f, -0.9f, 0.0f, 1.0f);
1206e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(  0.7f, -0.1f, 0.0f, 1.0f);
1207e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4( 0.11f,  0.2f, 0.0f, 1.0f);
1208e5c31af7Sopenharmony_ci			break;
1209e5c31af7Sopenharmony_ci	}
1210e5c31af7Sopenharmony_ci
1211e5c31af7Sopenharmony_ci	outLines.resize(4);
1212e5c31af7Sopenharmony_ci	outLines[0].positions[0] = outData[0];
1213e5c31af7Sopenharmony_ci	outLines[0].positions[1] = outData[1];
1214e5c31af7Sopenharmony_ci	outLines[1].positions[0] = outData[1];
1215e5c31af7Sopenharmony_ci	outLines[1].positions[1] = outData[2];
1216e5c31af7Sopenharmony_ci	outLines[2].positions[0] = outData[2];
1217e5c31af7Sopenharmony_ci	outLines[2].positions[1] = outData[3];
1218e5c31af7Sopenharmony_ci	outLines[3].positions[0] = outData[3];
1219e5c31af7Sopenharmony_ci	outLines[3].positions[1] = outData[0];
1220e5c31af7Sopenharmony_ci
1221e5c31af7Sopenharmony_ci	// log
1222e5c31af7Sopenharmony_ci	m_testCtx.getLog() << tcu::TestLog::Message << "Rendering line loop, width = " << getLineWidth() << ", " << outData.size() << " vertices." << tcu::TestLog::EndMessage;
1223e5c31af7Sopenharmony_ci	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1224e5c31af7Sopenharmony_ci	{
1225e5c31af7Sopenharmony_ci		m_testCtx.getLog()
1226e5c31af7Sopenharmony_ci			<< tcu::TestLog::Message
1227e5c31af7Sopenharmony_ci			<< "\t" << outData[vtxNdx]
1228e5c31af7Sopenharmony_ci			<< tcu::TestLog::EndMessage;
1229e5c31af7Sopenharmony_ci	}
1230e5c31af7Sopenharmony_ci}
1231e5c31af7Sopenharmony_ci
1232e5c31af7Sopenharmony_ciclass FillRuleCase : public BaseRenderingCase
1233e5c31af7Sopenharmony_ci{
1234e5c31af7Sopenharmony_cipublic:
1235e5c31af7Sopenharmony_ci	enum FillRuleCaseType
1236e5c31af7Sopenharmony_ci	{
1237e5c31af7Sopenharmony_ci		FILLRULECASE_BASIC = 0,
1238e5c31af7Sopenharmony_ci		FILLRULECASE_REVERSED,
1239e5c31af7Sopenharmony_ci		FILLRULECASE_CLIPPED_FULL,
1240e5c31af7Sopenharmony_ci		FILLRULECASE_CLIPPED_PARTIAL,
1241e5c31af7Sopenharmony_ci		FILLRULECASE_PROJECTED,
1242e5c31af7Sopenharmony_ci
1243e5c31af7Sopenharmony_ci		FILLRULECASE_LAST
1244e5c31af7Sopenharmony_ci	};
1245e5c31af7Sopenharmony_ci
1246e5c31af7Sopenharmony_ci							FillRuleCase		(Context& ctx, const char* name, const char* desc, FillRuleCaseType type, RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1247e5c31af7Sopenharmony_ci							~FillRuleCase		(void);
1248e5c31af7Sopenharmony_ci	IterateResult			iterate				(void);
1249e5c31af7Sopenharmony_ci
1250e5c31af7Sopenharmony_ciprivate:
1251e5c31af7Sopenharmony_ci	int						getRenderSize		(FillRuleCase::FillRuleCaseType type) const;
1252e5c31af7Sopenharmony_ci	int						getNumIterations	(FillRuleCase::FillRuleCaseType type) const;
1253e5c31af7Sopenharmony_ci	void					generateTriangles	(int iteration, std::vector<tcu::Vec4>& outData) const;
1254e5c31af7Sopenharmony_ci
1255e5c31af7Sopenharmony_ci	const FillRuleCaseType	m_caseType;
1256e5c31af7Sopenharmony_ci	int						m_iteration;
1257e5c31af7Sopenharmony_ci	const int				m_iterationCount;
1258e5c31af7Sopenharmony_ci	bool					m_allIterationsPassed;
1259e5c31af7Sopenharmony_ci
1260e5c31af7Sopenharmony_ci};
1261e5c31af7Sopenharmony_ci
1262e5c31af7Sopenharmony_ciFillRuleCase::FillRuleCase (Context& ctx, const char* name, const char* desc, FillRuleCaseType type, RenderTarget renderTarget, int numSamples)
1263e5c31af7Sopenharmony_ci	: BaseRenderingCase		(ctx, name, desc, renderTarget, numSamples, getRenderSize(type))
1264e5c31af7Sopenharmony_ci	, m_caseType			(type)
1265e5c31af7Sopenharmony_ci	, m_iteration			(0)
1266e5c31af7Sopenharmony_ci	, m_iterationCount		(getNumIterations(type))
1267e5c31af7Sopenharmony_ci	, m_allIterationsPassed	(true)
1268e5c31af7Sopenharmony_ci{
1269e5c31af7Sopenharmony_ci	DE_ASSERT(type < FILLRULECASE_LAST);
1270e5c31af7Sopenharmony_ci}
1271e5c31af7Sopenharmony_ci
1272e5c31af7Sopenharmony_ciFillRuleCase::~FillRuleCase (void)
1273e5c31af7Sopenharmony_ci{
1274e5c31af7Sopenharmony_ci	deinit();
1275e5c31af7Sopenharmony_ci}
1276e5c31af7Sopenharmony_ci
1277e5c31af7Sopenharmony_ciFillRuleCase::IterateResult FillRuleCase::iterate (void)
1278e5c31af7Sopenharmony_ci{
1279e5c31af7Sopenharmony_ci	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1280e5c31af7Sopenharmony_ci	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), iterationDescription, iterationDescription);
1281e5c31af7Sopenharmony_ci	const int								thresholdRed			= 1 << (8 - getPixelFormat().redBits);
1282e5c31af7Sopenharmony_ci	const int								thresholdGreen			= 1 << (8 - getPixelFormat().greenBits);
1283e5c31af7Sopenharmony_ci	const int								thresholdBlue			= 1 << (8 - getPixelFormat().blueBits);
1284e5c31af7Sopenharmony_ci	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
1285e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>					drawBuffer;
1286e5c31af7Sopenharmony_ci	bool									imageShown				= false;
1287e5c31af7Sopenharmony_ci
1288e5c31af7Sopenharmony_ci	generateTriangles(m_iteration, drawBuffer);
1289e5c31af7Sopenharmony_ci
1290e5c31af7Sopenharmony_ci	// draw image
1291e5c31af7Sopenharmony_ci	{
1292e5c31af7Sopenharmony_ci		const glw::Functions&			gl				= m_context.getRenderContext().getFunctions();
1293e5c31af7Sopenharmony_ci		const std::vector<tcu::Vec4>	colorBuffer		(drawBuffer.size(), tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f));
1294e5c31af7Sopenharmony_ci
1295e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Drawing gray triangles with shared edges.\nEnabling additive blending to detect overlapping fragments." << tcu::TestLog::EndMessage;
1296e5c31af7Sopenharmony_ci
1297e5c31af7Sopenharmony_ci		gl.enable(GL_BLEND);
1298e5c31af7Sopenharmony_ci		gl.blendEquation(GL_FUNC_ADD);
1299e5c31af7Sopenharmony_ci		gl.blendFunc(GL_ONE, GL_ONE);
1300e5c31af7Sopenharmony_ci		drawPrimitives(resultImage, drawBuffer, colorBuffer, GL_TRIANGLES);
1301e5c31af7Sopenharmony_ci	}
1302e5c31af7Sopenharmony_ci
1303e5c31af7Sopenharmony_ci	// verify no overdraw
1304e5c31af7Sopenharmony_ci	{
1305e5c31af7Sopenharmony_ci		const tcu::RGBA	triangleColor	= tcu::RGBA(127, 127, 127, 255);
1306e5c31af7Sopenharmony_ci		bool			overdraw		= false;
1307e5c31af7Sopenharmony_ci
1308e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result." << tcu::TestLog::EndMessage;
1309e5c31af7Sopenharmony_ci
1310e5c31af7Sopenharmony_ci		for (int y = 0; y < resultImage.getHeight(); ++y)
1311e5c31af7Sopenharmony_ci		for (int x = 0; x < resultImage.getWidth();  ++x)
1312e5c31af7Sopenharmony_ci		{
1313e5c31af7Sopenharmony_ci			const tcu::RGBA color = resultImage.getPixel(x, y);
1314e5c31af7Sopenharmony_ci
1315e5c31af7Sopenharmony_ci			// color values are greater than triangle color? Allow lower values for multisampled edges and background.
1316e5c31af7Sopenharmony_ci			if ((color.getRed()   - triangleColor.getRed())   > thresholdRed   ||
1317e5c31af7Sopenharmony_ci				(color.getGreen() - triangleColor.getGreen()) > thresholdGreen ||
1318e5c31af7Sopenharmony_ci				(color.getBlue()  - triangleColor.getBlue())  > thresholdBlue)
1319e5c31af7Sopenharmony_ci				overdraw = true;
1320e5c31af7Sopenharmony_ci		}
1321e5c31af7Sopenharmony_ci
1322e5c31af7Sopenharmony_ci		// results
1323e5c31af7Sopenharmony_ci		if (!overdraw)
1324e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "No overlapping fragments detected." << tcu::TestLog::EndMessage;
1325e5c31af7Sopenharmony_ci		else
1326e5c31af7Sopenharmony_ci		{
1327e5c31af7Sopenharmony_ci			m_testCtx.getLog()	<< tcu::TestLog::Message << "Overlapping fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1328e5c31af7Sopenharmony_ci			m_testCtx.getLog()	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1329e5c31af7Sopenharmony_ci								<< tcu::TestLog::Image("Result", "Result", resultImage)
1330e5c31af7Sopenharmony_ci								<< tcu::TestLog::EndImageSet;
1331e5c31af7Sopenharmony_ci
1332e5c31af7Sopenharmony_ci			imageShown = true;
1333e5c31af7Sopenharmony_ci			m_allIterationsPassed = false;
1334e5c31af7Sopenharmony_ci		}
1335e5c31af7Sopenharmony_ci	}
1336e5c31af7Sopenharmony_ci
1337e5c31af7Sopenharmony_ci	// verify no missing fragments in the full viewport case
1338e5c31af7Sopenharmony_ci	if (m_caseType == FILLRULECASE_CLIPPED_FULL)
1339e5c31af7Sopenharmony_ci	{
1340e5c31af7Sopenharmony_ci		bool missingFragments = false;
1341e5c31af7Sopenharmony_ci
1342e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Searching missing fragments." << tcu::TestLog::EndMessage;
1343e5c31af7Sopenharmony_ci
1344e5c31af7Sopenharmony_ci		for (int y = 0; y < resultImage.getHeight(); ++y)
1345e5c31af7Sopenharmony_ci		for (int x = 0; x < resultImage.getWidth();  ++x)
1346e5c31af7Sopenharmony_ci		{
1347e5c31af7Sopenharmony_ci			const tcu::RGBA color = resultImage.getPixel(x, y);
1348e5c31af7Sopenharmony_ci
1349e5c31af7Sopenharmony_ci			// black? (background)
1350e5c31af7Sopenharmony_ci			if (color.getRed()   <= thresholdRed   ||
1351e5c31af7Sopenharmony_ci				color.getGreen() <= thresholdGreen ||
1352e5c31af7Sopenharmony_ci				color.getBlue()  <= thresholdBlue)
1353e5c31af7Sopenharmony_ci				missingFragments = true;
1354e5c31af7Sopenharmony_ci		}
1355e5c31af7Sopenharmony_ci
1356e5c31af7Sopenharmony_ci		// results
1357e5c31af7Sopenharmony_ci		if (!missingFragments)
1358e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "No missing fragments detected." << tcu::TestLog::EndMessage;
1359e5c31af7Sopenharmony_ci		else
1360e5c31af7Sopenharmony_ci		{
1361e5c31af7Sopenharmony_ci			m_testCtx.getLog()	<< tcu::TestLog::Message << "Missing fragments detected, image is not valid." << tcu::TestLog::EndMessage;
1362e5c31af7Sopenharmony_ci
1363e5c31af7Sopenharmony_ci			if (!imageShown)
1364e5c31af7Sopenharmony_ci			{
1365e5c31af7Sopenharmony_ci				m_testCtx.getLog()	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
1366e5c31af7Sopenharmony_ci									<< tcu::TestLog::Image("Result", "Result", resultImage)
1367e5c31af7Sopenharmony_ci									<< tcu::TestLog::EndImageSet;
1368e5c31af7Sopenharmony_ci			}
1369e5c31af7Sopenharmony_ci
1370e5c31af7Sopenharmony_ci			m_allIterationsPassed = false;
1371e5c31af7Sopenharmony_ci		}
1372e5c31af7Sopenharmony_ci	}
1373e5c31af7Sopenharmony_ci
1374e5c31af7Sopenharmony_ci	// result
1375e5c31af7Sopenharmony_ci	if (++m_iteration == m_iterationCount)
1376e5c31af7Sopenharmony_ci	{
1377e5c31af7Sopenharmony_ci		if (m_allIterationsPassed)
1378e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1379e5c31af7Sopenharmony_ci		else
1380e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixels");
1381e5c31af7Sopenharmony_ci
1382e5c31af7Sopenharmony_ci		return STOP;
1383e5c31af7Sopenharmony_ci	}
1384e5c31af7Sopenharmony_ci	else
1385e5c31af7Sopenharmony_ci		return CONTINUE;
1386e5c31af7Sopenharmony_ci}
1387e5c31af7Sopenharmony_ci
1388e5c31af7Sopenharmony_ciint FillRuleCase::getRenderSize (FillRuleCase::FillRuleCaseType type) const
1389e5c31af7Sopenharmony_ci{
1390e5c31af7Sopenharmony_ci	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1391e5c31af7Sopenharmony_ci		return DEFAULT_RENDER_SIZE / 4;
1392e5c31af7Sopenharmony_ci	else
1393e5c31af7Sopenharmony_ci		return DEFAULT_RENDER_SIZE;
1394e5c31af7Sopenharmony_ci}
1395e5c31af7Sopenharmony_ci
1396e5c31af7Sopenharmony_ciint FillRuleCase::getNumIterations (FillRuleCase::FillRuleCaseType type) const
1397e5c31af7Sopenharmony_ci{
1398e5c31af7Sopenharmony_ci	if (type == FILLRULECASE_CLIPPED_FULL || type == FILLRULECASE_CLIPPED_PARTIAL)
1399e5c31af7Sopenharmony_ci		return 15;
1400e5c31af7Sopenharmony_ci	else
1401e5c31af7Sopenharmony_ci		return 2;
1402e5c31af7Sopenharmony_ci}
1403e5c31af7Sopenharmony_ci
1404e5c31af7Sopenharmony_civoid FillRuleCase::generateTriangles (int iteration, std::vector<tcu::Vec4>& outData) const
1405e5c31af7Sopenharmony_ci{
1406e5c31af7Sopenharmony_ci	switch (m_caseType)
1407e5c31af7Sopenharmony_ci	{
1408e5c31af7Sopenharmony_ci		case FILLRULECASE_BASIC:
1409e5c31af7Sopenharmony_ci		case FILLRULECASE_REVERSED:
1410e5c31af7Sopenharmony_ci		case FILLRULECASE_PROJECTED:
1411e5c31af7Sopenharmony_ci		{
1412e5c31af7Sopenharmony_ci			const int	numRows		= 4;
1413e5c31af7Sopenharmony_ci			const int	numColumns	= 4;
1414e5c31af7Sopenharmony_ci			const float	quadSide	= 0.15f;
1415e5c31af7Sopenharmony_ci			de::Random	rnd			(0xabcd);
1416e5c31af7Sopenharmony_ci
1417e5c31af7Sopenharmony_ci			outData.resize(6 * numRows * numColumns);
1418e5c31af7Sopenharmony_ci
1419e5c31af7Sopenharmony_ci			for (int col = 0; col < numColumns; ++col)
1420e5c31af7Sopenharmony_ci			for (int row = 0; row < numRows;    ++row)
1421e5c31af7Sopenharmony_ci			{
1422e5c31af7Sopenharmony_ci				const tcu::Vec2 center		= tcu::Vec2(((float)row + 0.5f) / (float)numRows * 2.0f - 1.0f, ((float)col + 0.5f) / (float)numColumns * 2.0f - 1.0f);
1423e5c31af7Sopenharmony_ci				const float		rotation	= (float)(iteration * numColumns * numRows + col * numRows + row) / (float)(m_iterationCount * numColumns * numRows) * DE_PI / 2.0f;
1424e5c31af7Sopenharmony_ci				const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1425e5c31af7Sopenharmony_ci				const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
1426e5c31af7Sopenharmony_ci				const tcu::Vec2 quad[4]		=
1427e5c31af7Sopenharmony_ci				{
1428e5c31af7Sopenharmony_ci					center + sideH + sideV,
1429e5c31af7Sopenharmony_ci					center + sideH - sideV,
1430e5c31af7Sopenharmony_ci					center - sideH - sideV,
1431e5c31af7Sopenharmony_ci					center - sideH + sideV,
1432e5c31af7Sopenharmony_ci				};
1433e5c31af7Sopenharmony_ci
1434e5c31af7Sopenharmony_ci				if (m_caseType == FILLRULECASE_BASIC)
1435e5c31af7Sopenharmony_ci				{
1436e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1437e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1438e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1439e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1440e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1441e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1442e5c31af7Sopenharmony_ci				}
1443e5c31af7Sopenharmony_ci				else if (m_caseType == FILLRULECASE_REVERSED)
1444e5c31af7Sopenharmony_ci				{
1445e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1446e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1447e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1448e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1449e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1450e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1451e5c31af7Sopenharmony_ci				}
1452e5c31af7Sopenharmony_ci				else if (m_caseType == FILLRULECASE_PROJECTED)
1453e5c31af7Sopenharmony_ci				{
1454e5c31af7Sopenharmony_ci					const float w0 = rnd.getFloat(0.1f, 4.0f);
1455e5c31af7Sopenharmony_ci					const float w1 = rnd.getFloat(0.1f, 4.0f);
1456e5c31af7Sopenharmony_ci					const float w2 = rnd.getFloat(0.1f, 4.0f);
1457e5c31af7Sopenharmony_ci					const float w3 = rnd.getFloat(0.1f, 4.0f);
1458e5c31af7Sopenharmony_ci
1459e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 0] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1460e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 1] = tcu::Vec4(quad[1].x() * w1, quad[1].y() * w1, 0.0f, w1);
1461e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 2] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1462e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 3] = tcu::Vec4(quad[2].x() * w2, quad[2].y() * w2, 0.0f, w2);
1463e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 4] = tcu::Vec4(quad[0].x() * w0, quad[0].y() * w0, 0.0f, w0);
1464e5c31af7Sopenharmony_ci					outData[6 * (col * numRows + row) + 5] = tcu::Vec4(quad[3].x() * w3, quad[3].y() * w3, 0.0f, w3);
1465e5c31af7Sopenharmony_ci				}
1466e5c31af7Sopenharmony_ci				else
1467e5c31af7Sopenharmony_ci					DE_ASSERT(DE_FALSE);
1468e5c31af7Sopenharmony_ci			}
1469e5c31af7Sopenharmony_ci
1470e5c31af7Sopenharmony_ci			break;
1471e5c31af7Sopenharmony_ci		}
1472e5c31af7Sopenharmony_ci
1473e5c31af7Sopenharmony_ci		case FILLRULECASE_CLIPPED_PARTIAL:
1474e5c31af7Sopenharmony_ci		case FILLRULECASE_CLIPPED_FULL:
1475e5c31af7Sopenharmony_ci		{
1476e5c31af7Sopenharmony_ci			const float		quadSide	= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (1.0f) : (2.0f);
1477e5c31af7Sopenharmony_ci			const tcu::Vec2 center		= (m_caseType == FILLRULECASE_CLIPPED_PARTIAL) ? (tcu::Vec2(0.5f, 0.5f)) : (tcu::Vec2(0.0f, 0.0f));
1478e5c31af7Sopenharmony_ci			const float		rotation	= (float)(iteration) / (float)(m_iterationCount - 1) * DE_PI / 2.0f;
1479e5c31af7Sopenharmony_ci			const tcu::Vec2 sideH		= quadSide * tcu::Vec2(deFloatCos(rotation), deFloatSin(rotation));
1480e5c31af7Sopenharmony_ci			const tcu::Vec2 sideV		= tcu::Vec2(sideH.y(), -sideH.x());
1481e5c31af7Sopenharmony_ci			const tcu::Vec2 quad[4]		=
1482e5c31af7Sopenharmony_ci			{
1483e5c31af7Sopenharmony_ci				center + sideH + sideV,
1484e5c31af7Sopenharmony_ci				center + sideH - sideV,
1485e5c31af7Sopenharmony_ci				center - sideH - sideV,
1486e5c31af7Sopenharmony_ci				center - sideH + sideV,
1487e5c31af7Sopenharmony_ci			};
1488e5c31af7Sopenharmony_ci
1489e5c31af7Sopenharmony_ci			outData.resize(6);
1490e5c31af7Sopenharmony_ci			outData[0] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1491e5c31af7Sopenharmony_ci			outData[1] = tcu::Vec4(quad[1].x(), quad[1].y(), 0.0f, 1.0f);
1492e5c31af7Sopenharmony_ci			outData[2] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1493e5c31af7Sopenharmony_ci			outData[3] = tcu::Vec4(quad[2].x(), quad[2].y(), 0.0f, 1.0f);
1494e5c31af7Sopenharmony_ci			outData[4] = tcu::Vec4(quad[0].x(), quad[0].y(), 0.0f, 1.0f);
1495e5c31af7Sopenharmony_ci			outData[5] = tcu::Vec4(quad[3].x(), quad[3].y(), 0.0f, 1.0f);
1496e5c31af7Sopenharmony_ci			break;
1497e5c31af7Sopenharmony_ci		}
1498e5c31af7Sopenharmony_ci
1499e5c31af7Sopenharmony_ci		default:
1500e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
1501e5c31af7Sopenharmony_ci	}
1502e5c31af7Sopenharmony_ci}
1503e5c31af7Sopenharmony_ci
1504e5c31af7Sopenharmony_ciclass CullingTest : public BaseRenderingCase
1505e5c31af7Sopenharmony_ci{
1506e5c31af7Sopenharmony_cipublic:
1507e5c31af7Sopenharmony_ci						CullingTest			(Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder);
1508e5c31af7Sopenharmony_ci						~CullingTest		(void);
1509e5c31af7Sopenharmony_ci	IterateResult		iterate				(void);
1510e5c31af7Sopenharmony_ci
1511e5c31af7Sopenharmony_ciprivate:
1512e5c31af7Sopenharmony_ci	void				generateVertices	(std::vector<tcu::Vec4>& outData) const;
1513e5c31af7Sopenharmony_ci	void				extractTriangles	(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const;
1514e5c31af7Sopenharmony_ci	bool				triangleOrder		(const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const;
1515e5c31af7Sopenharmony_ci
1516e5c31af7Sopenharmony_ci	const glw::GLenum	m_cullMode;
1517e5c31af7Sopenharmony_ci	const glw::GLenum	m_primitive;
1518e5c31af7Sopenharmony_ci	const glw::GLenum	m_faceOrder;
1519e5c31af7Sopenharmony_ci};
1520e5c31af7Sopenharmony_ci
1521e5c31af7Sopenharmony_ciCullingTest::CullingTest (Context& ctx, const char* name, const char* desc, glw::GLenum cullMode, glw::GLenum primitive, glw::GLenum faceOrder)
1522e5c31af7Sopenharmony_ci	: BaseRenderingCase	(ctx, name, desc, RENDERTARGET_DEFAULT, -1, DEFAULT_RENDER_SIZE)
1523e5c31af7Sopenharmony_ci	, m_cullMode		(cullMode)
1524e5c31af7Sopenharmony_ci	, m_primitive		(primitive)
1525e5c31af7Sopenharmony_ci	, m_faceOrder		(faceOrder)
1526e5c31af7Sopenharmony_ci{
1527e5c31af7Sopenharmony_ci}
1528e5c31af7Sopenharmony_ci
1529e5c31af7Sopenharmony_ciCullingTest::~CullingTest (void)
1530e5c31af7Sopenharmony_ci{
1531e5c31af7Sopenharmony_ci}
1532e5c31af7Sopenharmony_ci
1533e5c31af7Sopenharmony_ciCullingTest::IterateResult CullingTest::iterate (void)
1534e5c31af7Sopenharmony_ci{
1535e5c31af7Sopenharmony_ci	tcu::Surface									resultImage(m_renderSize, m_renderSize);
1536e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>							drawBuffer;
1537e5c31af7Sopenharmony_ci	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
1538e5c31af7Sopenharmony_ci
1539e5c31af7Sopenharmony_ci	// generate scene
1540e5c31af7Sopenharmony_ci	generateVertices(drawBuffer);
1541e5c31af7Sopenharmony_ci	extractTriangles(triangles, drawBuffer);
1542e5c31af7Sopenharmony_ci
1543e5c31af7Sopenharmony_ci	// draw image
1544e5c31af7Sopenharmony_ci	{
1545e5c31af7Sopenharmony_ci		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1546e5c31af7Sopenharmony_ci
1547e5c31af7Sopenharmony_ci		gl.enable(GL_CULL_FACE);
1548e5c31af7Sopenharmony_ci		gl.cullFace(m_cullMode);
1549e5c31af7Sopenharmony_ci		gl.frontFace(m_faceOrder);
1550e5c31af7Sopenharmony_ci
1551e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Setting front face to " << glu::getWindingName(m_faceOrder) << tcu::TestLog::EndMessage;
1552e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Setting cull face to " << glu::getFaceName(m_cullMode) << tcu::TestLog::EndMessage;
1553e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Drawing test pattern (" << glu::getPrimitiveTypeName(m_primitive) << ")" << tcu::TestLog::EndMessage;
1554e5c31af7Sopenharmony_ci
1555e5c31af7Sopenharmony_ci		drawPrimitives(resultImage, drawBuffer, m_primitive);
1556e5c31af7Sopenharmony_ci	}
1557e5c31af7Sopenharmony_ci
1558e5c31af7Sopenharmony_ci	// compare
1559e5c31af7Sopenharmony_ci	{
1560e5c31af7Sopenharmony_ci		RasterizationArguments	args;
1561e5c31af7Sopenharmony_ci		TriangleSceneSpec		scene;
1562e5c31af7Sopenharmony_ci
1563e5c31af7Sopenharmony_ci		args.numSamples		= m_numSamples;
1564e5c31af7Sopenharmony_ci		args.subpixelBits	= m_subpixelBits;
1565e5c31af7Sopenharmony_ci		args.redBits		= getPixelFormat().redBits;
1566e5c31af7Sopenharmony_ci		args.greenBits		= getPixelFormat().greenBits;
1567e5c31af7Sopenharmony_ci		args.blueBits		= getPixelFormat().blueBits;
1568e5c31af7Sopenharmony_ci
1569e5c31af7Sopenharmony_ci		scene.triangles.swap(triangles);
1570e5c31af7Sopenharmony_ci
1571e5c31af7Sopenharmony_ci		if (verifyTriangleGroupRasterization(resultImage, scene, args, m_testCtx.getLog(), tcu::VERIFICATIONMODE_WEAK))
1572e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1573e5c31af7Sopenharmony_ci		else
1574e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Incorrect rendering");
1575e5c31af7Sopenharmony_ci	}
1576e5c31af7Sopenharmony_ci
1577e5c31af7Sopenharmony_ci	return STOP;
1578e5c31af7Sopenharmony_ci}
1579e5c31af7Sopenharmony_ci
1580e5c31af7Sopenharmony_civoid CullingTest::generateVertices (std::vector<tcu::Vec4>& outData) const
1581e5c31af7Sopenharmony_ci{
1582e5c31af7Sopenharmony_ci	de::Random rnd(543210);
1583e5c31af7Sopenharmony_ci
1584e5c31af7Sopenharmony_ci	outData.resize(6);
1585e5c31af7Sopenharmony_ci	for (int vtxNdx = 0; vtxNdx < (int)outData.size(); ++vtxNdx)
1586e5c31af7Sopenharmony_ci	{
1587e5c31af7Sopenharmony_ci		outData[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1588e5c31af7Sopenharmony_ci		outData[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1589e5c31af7Sopenharmony_ci		outData[vtxNdx].z() = 0.0f;
1590e5c31af7Sopenharmony_ci		outData[vtxNdx].w() = 1.0f;
1591e5c31af7Sopenharmony_ci	}
1592e5c31af7Sopenharmony_ci}
1593e5c31af7Sopenharmony_ci
1594e5c31af7Sopenharmony_civoid CullingTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices) const
1595e5c31af7Sopenharmony_ci{
1596e5c31af7Sopenharmony_ci	const bool cullDirection = (m_cullMode == GL_FRONT) ^ (m_faceOrder == GL_CCW);
1597e5c31af7Sopenharmony_ci
1598e5c31af7Sopenharmony_ci	// No triangles
1599e5c31af7Sopenharmony_ci	if (m_cullMode == GL_FRONT_AND_BACK)
1600e5c31af7Sopenharmony_ci		return;
1601e5c31af7Sopenharmony_ci
1602e5c31af7Sopenharmony_ci	switch (m_primitive)
1603e5c31af7Sopenharmony_ci	{
1604e5c31af7Sopenharmony_ci		case GL_TRIANGLES:
1605e5c31af7Sopenharmony_ci		{
1606e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1607e5c31af7Sopenharmony_ci			{
1608e5c31af7Sopenharmony_ci				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1609e5c31af7Sopenharmony_ci				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1610e5c31af7Sopenharmony_ci				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1611e5c31af7Sopenharmony_ci
1612e5c31af7Sopenharmony_ci				if (triangleOrder(v0, v1, v2) != cullDirection)
1613e5c31af7Sopenharmony_ci				{
1614e5c31af7Sopenharmony_ci					TriangleSceneSpec::SceneTriangle tri;
1615e5c31af7Sopenharmony_ci					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
1616e5c31af7Sopenharmony_ci					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
1617e5c31af7Sopenharmony_ci					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
1618e5c31af7Sopenharmony_ci
1619e5c31af7Sopenharmony_ci					outTriangles.push_back(tri);
1620e5c31af7Sopenharmony_ci				}
1621e5c31af7Sopenharmony_ci			}
1622e5c31af7Sopenharmony_ci			break;
1623e5c31af7Sopenharmony_ci		}
1624e5c31af7Sopenharmony_ci
1625e5c31af7Sopenharmony_ci		case GL_TRIANGLE_STRIP:
1626e5c31af7Sopenharmony_ci		{
1627e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1628e5c31af7Sopenharmony_ci			{
1629e5c31af7Sopenharmony_ci				const tcu::Vec4& v0 = vertices[vtxNdx + 0];
1630e5c31af7Sopenharmony_ci				const tcu::Vec4& v1 = vertices[vtxNdx + 1];
1631e5c31af7Sopenharmony_ci				const tcu::Vec4& v2 = vertices[vtxNdx + 2];
1632e5c31af7Sopenharmony_ci
1633e5c31af7Sopenharmony_ci				if (triangleOrder(v0, v1, v2) != (cullDirection ^ (vtxNdx % 2 != 0)))
1634e5c31af7Sopenharmony_ci				{
1635e5c31af7Sopenharmony_ci					TriangleSceneSpec::SceneTriangle tri;
1636e5c31af7Sopenharmony_ci					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
1637e5c31af7Sopenharmony_ci					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
1638e5c31af7Sopenharmony_ci					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
1639e5c31af7Sopenharmony_ci
1640e5c31af7Sopenharmony_ci					outTriangles.push_back(tri);
1641e5c31af7Sopenharmony_ci				}
1642e5c31af7Sopenharmony_ci			}
1643e5c31af7Sopenharmony_ci			break;
1644e5c31af7Sopenharmony_ci		}
1645e5c31af7Sopenharmony_ci
1646e5c31af7Sopenharmony_ci		case GL_TRIANGLE_FAN:
1647e5c31af7Sopenharmony_ci		{
1648e5c31af7Sopenharmony_ci			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1649e5c31af7Sopenharmony_ci			{
1650e5c31af7Sopenharmony_ci				const tcu::Vec4& v0 = vertices[0];
1651e5c31af7Sopenharmony_ci				const tcu::Vec4& v1 = vertices[vtxNdx + 0];
1652e5c31af7Sopenharmony_ci				const tcu::Vec4& v2 = vertices[vtxNdx + 1];
1653e5c31af7Sopenharmony_ci
1654e5c31af7Sopenharmony_ci				if (triangleOrder(v0, v1, v2) != cullDirection)
1655e5c31af7Sopenharmony_ci				{
1656e5c31af7Sopenharmony_ci					TriangleSceneSpec::SceneTriangle tri;
1657e5c31af7Sopenharmony_ci					tri.positions[0] = v0;	tri.sharedEdge[0] = false;
1658e5c31af7Sopenharmony_ci					tri.positions[1] = v1;	tri.sharedEdge[1] = false;
1659e5c31af7Sopenharmony_ci					tri.positions[2] = v2;	tri.sharedEdge[2] = false;
1660e5c31af7Sopenharmony_ci
1661e5c31af7Sopenharmony_ci					outTriangles.push_back(tri);
1662e5c31af7Sopenharmony_ci				}
1663e5c31af7Sopenharmony_ci			}
1664e5c31af7Sopenharmony_ci			break;
1665e5c31af7Sopenharmony_ci		}
1666e5c31af7Sopenharmony_ci
1667e5c31af7Sopenharmony_ci		default:
1668e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1669e5c31af7Sopenharmony_ci	}
1670e5c31af7Sopenharmony_ci}
1671e5c31af7Sopenharmony_ci
1672e5c31af7Sopenharmony_cibool CullingTest::triangleOrder (const tcu::Vec4& v0, const tcu::Vec4& v1, const tcu::Vec4& v2) const
1673e5c31af7Sopenharmony_ci{
1674e5c31af7Sopenharmony_ci	const tcu::Vec2 s0 = v0.swizzle(0, 1) / v0.w();
1675e5c31af7Sopenharmony_ci	const tcu::Vec2 s1 = v1.swizzle(0, 1) / v1.w();
1676e5c31af7Sopenharmony_ci	const tcu::Vec2 s2 = v2.swizzle(0, 1) / v2.w();
1677e5c31af7Sopenharmony_ci
1678e5c31af7Sopenharmony_ci	// cross
1679e5c31af7Sopenharmony_ci	return ((s1.x() - s0.x()) * (s2.y() - s0.y()) - (s2.x() - s0.x()) * (s1.y() - s0.y())) < 0;
1680e5c31af7Sopenharmony_ci}
1681e5c31af7Sopenharmony_ci
1682e5c31af7Sopenharmony_ciclass TriangleInterpolationTest : public BaseRenderingCase
1683e5c31af7Sopenharmony_ci{
1684e5c31af7Sopenharmony_cipublic:
1685e5c31af7Sopenharmony_ci						TriangleInterpolationTest	(Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1686e5c31af7Sopenharmony_ci						~TriangleInterpolationTest	(void);
1687e5c31af7Sopenharmony_ci	IterateResult		iterate						(void);
1688e5c31af7Sopenharmony_ci
1689e5c31af7Sopenharmony_ciprivate:
1690e5c31af7Sopenharmony_ci	void				generateVertices			(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1691e5c31af7Sopenharmony_ci	void				extractTriangles			(std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1692e5c31af7Sopenharmony_ci
1693e5c31af7Sopenharmony_ci	const glw::GLenum	m_primitive;
1694e5c31af7Sopenharmony_ci	const bool			m_projective;
1695e5c31af7Sopenharmony_ci	const int			m_iterationCount;
1696e5c31af7Sopenharmony_ci
1697e5c31af7Sopenharmony_ci	int					m_iteration;
1698e5c31af7Sopenharmony_ci	bool				m_allIterationsPassed;
1699e5c31af7Sopenharmony_ci};
1700e5c31af7Sopenharmony_ci
1701e5c31af7Sopenharmony_ciTriangleInterpolationTest::TriangleInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, RenderTarget renderTarget, int numSamples)
1702e5c31af7Sopenharmony_ci	: BaseRenderingCase		(ctx, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
1703e5c31af7Sopenharmony_ci	, m_primitive			(primitive)
1704e5c31af7Sopenharmony_ci	, m_projective			((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1705e5c31af7Sopenharmony_ci	, m_iterationCount		(3)
1706e5c31af7Sopenharmony_ci	, m_iteration			(0)
1707e5c31af7Sopenharmony_ci	, m_allIterationsPassed	(true)
1708e5c31af7Sopenharmony_ci{
1709e5c31af7Sopenharmony_ci	m_flatshade = ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0);
1710e5c31af7Sopenharmony_ci}
1711e5c31af7Sopenharmony_ci
1712e5c31af7Sopenharmony_ciTriangleInterpolationTest::~TriangleInterpolationTest (void)
1713e5c31af7Sopenharmony_ci{
1714e5c31af7Sopenharmony_ci	deinit();
1715e5c31af7Sopenharmony_ci}
1716e5c31af7Sopenharmony_ci
1717e5c31af7Sopenharmony_ciTriangleInterpolationTest::IterateResult TriangleInterpolationTest::iterate (void)
1718e5c31af7Sopenharmony_ci{
1719e5c31af7Sopenharmony_ci	const std::string								iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1720e5c31af7Sopenharmony_ci	const tcu::ScopedLogSection						section					(m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1721e5c31af7Sopenharmony_ci	tcu::Surface									resultImage				(m_renderSize, m_renderSize);
1722e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>							drawBuffer;
1723e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>							colorBuffer;
1724e5c31af7Sopenharmony_ci	std::vector<TriangleSceneSpec::SceneTriangle>	triangles;
1725e5c31af7Sopenharmony_ci
1726e5c31af7Sopenharmony_ci	// generate scene
1727e5c31af7Sopenharmony_ci	generateVertices(m_iteration, drawBuffer, colorBuffer);
1728e5c31af7Sopenharmony_ci	extractTriangles(triangles, drawBuffer, colorBuffer);
1729e5c31af7Sopenharmony_ci
1730e5c31af7Sopenharmony_ci	// log
1731e5c31af7Sopenharmony_ci	{
1732e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
1733e5c31af7Sopenharmony_ci		for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
1734e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
1735e5c31af7Sopenharmony_ci	}
1736e5c31af7Sopenharmony_ci
1737e5c31af7Sopenharmony_ci	// draw image
1738e5c31af7Sopenharmony_ci	drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
1739e5c31af7Sopenharmony_ci
1740e5c31af7Sopenharmony_ci	// compare
1741e5c31af7Sopenharmony_ci	{
1742e5c31af7Sopenharmony_ci		RasterizationArguments	args;
1743e5c31af7Sopenharmony_ci		TriangleSceneSpec		scene;
1744e5c31af7Sopenharmony_ci
1745e5c31af7Sopenharmony_ci		args.numSamples		= m_numSamples;
1746e5c31af7Sopenharmony_ci		args.subpixelBits	= m_subpixelBits;
1747e5c31af7Sopenharmony_ci		args.redBits		= getPixelFormat().redBits;
1748e5c31af7Sopenharmony_ci		args.greenBits		= getPixelFormat().greenBits;
1749e5c31af7Sopenharmony_ci		args.blueBits		= getPixelFormat().blueBits;
1750e5c31af7Sopenharmony_ci
1751e5c31af7Sopenharmony_ci		scene.triangles.swap(triangles);
1752e5c31af7Sopenharmony_ci
1753e5c31af7Sopenharmony_ci		if (!verifyTriangleGroupInterpolation(resultImage, scene, args, m_testCtx.getLog()))
1754e5c31af7Sopenharmony_ci			m_allIterationsPassed = false;
1755e5c31af7Sopenharmony_ci	}
1756e5c31af7Sopenharmony_ci
1757e5c31af7Sopenharmony_ci	// result
1758e5c31af7Sopenharmony_ci	if (++m_iteration == m_iterationCount)
1759e5c31af7Sopenharmony_ci	{
1760e5c31af7Sopenharmony_ci		if (m_allIterationsPassed)
1761e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1762e5c31af7Sopenharmony_ci		else
1763e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
1764e5c31af7Sopenharmony_ci
1765e5c31af7Sopenharmony_ci		return STOP;
1766e5c31af7Sopenharmony_ci	}
1767e5c31af7Sopenharmony_ci	else
1768e5c31af7Sopenharmony_ci		return CONTINUE;
1769e5c31af7Sopenharmony_ci}
1770e5c31af7Sopenharmony_ci
1771e5c31af7Sopenharmony_civoid TriangleInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
1772e5c31af7Sopenharmony_ci{
1773e5c31af7Sopenharmony_ci	// use only red, green and blue
1774e5c31af7Sopenharmony_ci	const tcu::Vec4 colors[] =
1775e5c31af7Sopenharmony_ci	{
1776e5c31af7Sopenharmony_ci		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1777e5c31af7Sopenharmony_ci		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
1778e5c31af7Sopenharmony_ci		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1779e5c31af7Sopenharmony_ci	};
1780e5c31af7Sopenharmony_ci
1781e5c31af7Sopenharmony_ci	de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
1782e5c31af7Sopenharmony_ci
1783e5c31af7Sopenharmony_ci	outVertices.resize(6);
1784e5c31af7Sopenharmony_ci	outColors.resize(6);
1785e5c31af7Sopenharmony_ci
1786e5c31af7Sopenharmony_ci	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
1787e5c31af7Sopenharmony_ci	{
1788e5c31af7Sopenharmony_ci		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
1789e5c31af7Sopenharmony_ci		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
1790e5c31af7Sopenharmony_ci		outVertices[vtxNdx].z() = 0.0f;
1791e5c31af7Sopenharmony_ci
1792e5c31af7Sopenharmony_ci		if (!m_projective)
1793e5c31af7Sopenharmony_ci			outVertices[vtxNdx].w() = 1.0f;
1794e5c31af7Sopenharmony_ci		else
1795e5c31af7Sopenharmony_ci		{
1796e5c31af7Sopenharmony_ci			const float w = rnd.getFloat(0.2f, 4.0f);
1797e5c31af7Sopenharmony_ci
1798e5c31af7Sopenharmony_ci			outVertices[vtxNdx].x() *= w;
1799e5c31af7Sopenharmony_ci			outVertices[vtxNdx].y() *= w;
1800e5c31af7Sopenharmony_ci			outVertices[vtxNdx].z() *= w;
1801e5c31af7Sopenharmony_ci			outVertices[vtxNdx].w() = w;
1802e5c31af7Sopenharmony_ci		}
1803e5c31af7Sopenharmony_ci
1804e5c31af7Sopenharmony_ci		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
1805e5c31af7Sopenharmony_ci	}
1806e5c31af7Sopenharmony_ci}
1807e5c31af7Sopenharmony_ci
1808e5c31af7Sopenharmony_civoid TriangleInterpolationTest::extractTriangles (std::vector<TriangleSceneSpec::SceneTriangle>& outTriangles, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
1809e5c31af7Sopenharmony_ci{
1810e5c31af7Sopenharmony_ci	switch (m_primitive)
1811e5c31af7Sopenharmony_ci	{
1812e5c31af7Sopenharmony_ci		case GL_TRIANGLES:
1813e5c31af7Sopenharmony_ci		{
1814e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; vtxNdx += 3)
1815e5c31af7Sopenharmony_ci			{
1816e5c31af7Sopenharmony_ci				TriangleSceneSpec::SceneTriangle tri;
1817e5c31af7Sopenharmony_ci				tri.positions[0]	= vertices[vtxNdx + 0];
1818e5c31af7Sopenharmony_ci				tri.positions[1]	= vertices[vtxNdx + 1];
1819e5c31af7Sopenharmony_ci				tri.positions[2]	= vertices[vtxNdx + 2];
1820e5c31af7Sopenharmony_ci				tri.sharedEdge[0]	= false;
1821e5c31af7Sopenharmony_ci				tri.sharedEdge[1]	= false;
1822e5c31af7Sopenharmony_ci				tri.sharedEdge[2]	= false;
1823e5c31af7Sopenharmony_ci
1824e5c31af7Sopenharmony_ci				if (m_flatshade)
1825e5c31af7Sopenharmony_ci				{
1826e5c31af7Sopenharmony_ci					tri.colors[0] = colors[vtxNdx + 2];
1827e5c31af7Sopenharmony_ci					tri.colors[1] = colors[vtxNdx + 2];
1828e5c31af7Sopenharmony_ci					tri.colors[2] = colors[vtxNdx + 2];
1829e5c31af7Sopenharmony_ci				}
1830e5c31af7Sopenharmony_ci				else
1831e5c31af7Sopenharmony_ci				{
1832e5c31af7Sopenharmony_ci					tri.colors[0] = colors[vtxNdx + 0];
1833e5c31af7Sopenharmony_ci					tri.colors[1] = colors[vtxNdx + 1];
1834e5c31af7Sopenharmony_ci					tri.colors[2] = colors[vtxNdx + 2];
1835e5c31af7Sopenharmony_ci				}
1836e5c31af7Sopenharmony_ci
1837e5c31af7Sopenharmony_ci				outTriangles.push_back(tri);
1838e5c31af7Sopenharmony_ci			}
1839e5c31af7Sopenharmony_ci			break;
1840e5c31af7Sopenharmony_ci		}
1841e5c31af7Sopenharmony_ci
1842e5c31af7Sopenharmony_ci		case GL_TRIANGLE_STRIP:
1843e5c31af7Sopenharmony_ci		{
1844e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 2; ++vtxNdx)
1845e5c31af7Sopenharmony_ci			{
1846e5c31af7Sopenharmony_ci				TriangleSceneSpec::SceneTriangle tri;
1847e5c31af7Sopenharmony_ci				tri.positions[0]	= vertices[vtxNdx + 0];
1848e5c31af7Sopenharmony_ci				tri.positions[1]	= vertices[vtxNdx + 1];
1849e5c31af7Sopenharmony_ci				tri.positions[2]	= vertices[vtxNdx + 2];
1850e5c31af7Sopenharmony_ci				tri.sharedEdge[0]	= false;
1851e5c31af7Sopenharmony_ci				tri.sharedEdge[1]	= false;
1852e5c31af7Sopenharmony_ci				tri.sharedEdge[2]	= false;
1853e5c31af7Sopenharmony_ci
1854e5c31af7Sopenharmony_ci				if (m_flatshade)
1855e5c31af7Sopenharmony_ci				{
1856e5c31af7Sopenharmony_ci					tri.colors[0] = colors[vtxNdx + 2];
1857e5c31af7Sopenharmony_ci					tri.colors[1] = colors[vtxNdx + 2];
1858e5c31af7Sopenharmony_ci					tri.colors[2] = colors[vtxNdx + 2];
1859e5c31af7Sopenharmony_ci				}
1860e5c31af7Sopenharmony_ci				else
1861e5c31af7Sopenharmony_ci				{
1862e5c31af7Sopenharmony_ci					tri.colors[0] = colors[vtxNdx + 0];
1863e5c31af7Sopenharmony_ci					tri.colors[1] = colors[vtxNdx + 1];
1864e5c31af7Sopenharmony_ci					tri.colors[2] = colors[vtxNdx + 2];
1865e5c31af7Sopenharmony_ci				}
1866e5c31af7Sopenharmony_ci
1867e5c31af7Sopenharmony_ci				outTriangles.push_back(tri);
1868e5c31af7Sopenharmony_ci			}
1869e5c31af7Sopenharmony_ci			break;
1870e5c31af7Sopenharmony_ci		}
1871e5c31af7Sopenharmony_ci
1872e5c31af7Sopenharmony_ci		case GL_TRIANGLE_FAN:
1873e5c31af7Sopenharmony_ci		{
1874e5c31af7Sopenharmony_ci			for (int vtxNdx = 1; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
1875e5c31af7Sopenharmony_ci			{
1876e5c31af7Sopenharmony_ci				TriangleSceneSpec::SceneTriangle tri;
1877e5c31af7Sopenharmony_ci				tri.positions[0]	= vertices[0];
1878e5c31af7Sopenharmony_ci				tri.positions[1]	= vertices[vtxNdx + 0];
1879e5c31af7Sopenharmony_ci				tri.positions[2]	= vertices[vtxNdx + 1];
1880e5c31af7Sopenharmony_ci				tri.sharedEdge[0]	= false;
1881e5c31af7Sopenharmony_ci				tri.sharedEdge[1]	= false;
1882e5c31af7Sopenharmony_ci				tri.sharedEdge[2]	= false;
1883e5c31af7Sopenharmony_ci
1884e5c31af7Sopenharmony_ci				if (m_flatshade)
1885e5c31af7Sopenharmony_ci				{
1886e5c31af7Sopenharmony_ci					tri.colors[0] = colors[vtxNdx + 1];
1887e5c31af7Sopenharmony_ci					tri.colors[1] = colors[vtxNdx + 1];
1888e5c31af7Sopenharmony_ci					tri.colors[2] = colors[vtxNdx + 1];
1889e5c31af7Sopenharmony_ci				}
1890e5c31af7Sopenharmony_ci				else
1891e5c31af7Sopenharmony_ci				{
1892e5c31af7Sopenharmony_ci					tri.colors[0] = colors[0];
1893e5c31af7Sopenharmony_ci					tri.colors[1] = colors[vtxNdx + 0];
1894e5c31af7Sopenharmony_ci					tri.colors[2] = colors[vtxNdx + 1];
1895e5c31af7Sopenharmony_ci				}
1896e5c31af7Sopenharmony_ci
1897e5c31af7Sopenharmony_ci				outTriangles.push_back(tri);
1898e5c31af7Sopenharmony_ci			}
1899e5c31af7Sopenharmony_ci			break;
1900e5c31af7Sopenharmony_ci		}
1901e5c31af7Sopenharmony_ci
1902e5c31af7Sopenharmony_ci		default:
1903e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1904e5c31af7Sopenharmony_ci	}
1905e5c31af7Sopenharmony_ci}
1906e5c31af7Sopenharmony_ci
1907e5c31af7Sopenharmony_ciclass LineInterpolationTest : public BaseRenderingCase
1908e5c31af7Sopenharmony_ci{
1909e5c31af7Sopenharmony_cipublic:
1910e5c31af7Sopenharmony_ci							LineInterpolationTest	(Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, PrimitiveWideness wideness, RenderTarget renderTarget = RENDERTARGET_DEFAULT, int numSamples = -1);
1911e5c31af7Sopenharmony_ci							~LineInterpolationTest	(void);
1912e5c31af7Sopenharmony_ci
1913e5c31af7Sopenharmony_ci	void					init					(void);
1914e5c31af7Sopenharmony_ci	IterateResult			iterate					(void);
1915e5c31af7Sopenharmony_ci
1916e5c31af7Sopenharmony_ciprivate:
1917e5c31af7Sopenharmony_ci	void					generateVertices		(int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const;
1918e5c31af7Sopenharmony_ci	void					extractLines			(std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const;
1919e5c31af7Sopenharmony_ci	float					getLineWidth			(void) const;
1920e5c31af7Sopenharmony_ci
1921e5c31af7Sopenharmony_ci	const glw::GLenum		m_primitive;
1922e5c31af7Sopenharmony_ci	const bool				m_projective;
1923e5c31af7Sopenharmony_ci	const int				m_iterationCount;
1924e5c31af7Sopenharmony_ci	const PrimitiveWideness	m_primitiveWideness;
1925e5c31af7Sopenharmony_ci
1926e5c31af7Sopenharmony_ci	int						m_iteration;
1927e5c31af7Sopenharmony_ci	tcu::ResultCollector	m_result;
1928e5c31af7Sopenharmony_ci	float					m_maxLineWidth;
1929e5c31af7Sopenharmony_ci	std::vector<float>		m_lineWidths;
1930e5c31af7Sopenharmony_ci};
1931e5c31af7Sopenharmony_ci
1932e5c31af7Sopenharmony_ciLineInterpolationTest::LineInterpolationTest (Context& ctx, const char* name, const char* desc, glw::GLenum primitive, int flags, PrimitiveWideness wideness, RenderTarget renderTarget, int numSamples)
1933e5c31af7Sopenharmony_ci	: BaseRenderingCase		(ctx, name, desc, renderTarget, numSamples, DEFAULT_RENDER_SIZE)
1934e5c31af7Sopenharmony_ci	, m_primitive			(primitive)
1935e5c31af7Sopenharmony_ci	, m_projective			((flags & INTERPOLATIONFLAGS_PROJECTED) != 0)
1936e5c31af7Sopenharmony_ci	, m_iterationCount		(3)
1937e5c31af7Sopenharmony_ci	, m_primitiveWideness	(wideness)
1938e5c31af7Sopenharmony_ci	, m_iteration			(0)
1939e5c31af7Sopenharmony_ci	, m_maxLineWidth		(1.0f)
1940e5c31af7Sopenharmony_ci{
1941e5c31af7Sopenharmony_ci	m_flatshade = ((flags & INTERPOLATIONFLAGS_FLATSHADE) != 0);
1942e5c31af7Sopenharmony_ci}
1943e5c31af7Sopenharmony_ci
1944e5c31af7Sopenharmony_ciLineInterpolationTest::~LineInterpolationTest (void)
1945e5c31af7Sopenharmony_ci{
1946e5c31af7Sopenharmony_ci	deinit();
1947e5c31af7Sopenharmony_ci}
1948e5c31af7Sopenharmony_ci
1949e5c31af7Sopenharmony_civoid LineInterpolationTest::init (void)
1950e5c31af7Sopenharmony_ci{
1951e5c31af7Sopenharmony_ci	// create line widths
1952e5c31af7Sopenharmony_ci	if (m_primitiveWideness == PRIMITIVEWIDENESS_NARROW)
1953e5c31af7Sopenharmony_ci	{
1954e5c31af7Sopenharmony_ci		m_lineWidths.resize(m_iterationCount, 1.0f);
1955e5c31af7Sopenharmony_ci	}
1956e5c31af7Sopenharmony_ci	else if (m_primitiveWideness == PRIMITIVEWIDENESS_WIDE)
1957e5c31af7Sopenharmony_ci	{
1958e5c31af7Sopenharmony_ci		float range[2] = { 0.0f, 0.0f };
1959e5c31af7Sopenharmony_ci		m_context.getRenderContext().getFunctions().getFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
1960e5c31af7Sopenharmony_ci
1961e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "ALIASED_LINE_WIDTH_RANGE = [" << range[0] << ", " << range[1] << "]" << tcu::TestLog::EndMessage;
1962e5c31af7Sopenharmony_ci
1963e5c31af7Sopenharmony_ci		// no wide line support
1964e5c31af7Sopenharmony_ci		if (range[1] <= 1.0f)
1965e5c31af7Sopenharmony_ci			throw tcu::NotSupportedError("wide line support required");
1966e5c31af7Sopenharmony_ci
1967e5c31af7Sopenharmony_ci		// set hand picked sizes
1968e5c31af7Sopenharmony_ci		m_lineWidths.push_back(5.0f);
1969e5c31af7Sopenharmony_ci		m_lineWidths.push_back(10.0f);
1970e5c31af7Sopenharmony_ci		m_lineWidths.push_back(range[1]);
1971e5c31af7Sopenharmony_ci		DE_ASSERT((int)m_lineWidths.size() == m_iterationCount);
1972e5c31af7Sopenharmony_ci
1973e5c31af7Sopenharmony_ci		m_maxLineWidth = range[1];
1974e5c31af7Sopenharmony_ci	}
1975e5c31af7Sopenharmony_ci	else
1976e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1977e5c31af7Sopenharmony_ci
1978e5c31af7Sopenharmony_ci	// init parent
1979e5c31af7Sopenharmony_ci	BaseRenderingCase::init();
1980e5c31af7Sopenharmony_ci}
1981e5c31af7Sopenharmony_ci
1982e5c31af7Sopenharmony_ciLineInterpolationTest::IterateResult LineInterpolationTest::iterate (void)
1983e5c31af7Sopenharmony_ci{
1984e5c31af7Sopenharmony_ci	const std::string						iterationDescription	= "Test iteration " + de::toString(m_iteration+1) + " / " + de::toString(m_iterationCount);
1985e5c31af7Sopenharmony_ci	const tcu::ScopedLogSection				section					(m_testCtx.getLog(), "Iteration" + de::toString(m_iteration+1), iterationDescription);
1986e5c31af7Sopenharmony_ci	const float								lineWidth				= getLineWidth();
1987e5c31af7Sopenharmony_ci	tcu::Surface							resultImage				(m_renderSize, m_renderSize);
1988e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>					drawBuffer;
1989e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4>					colorBuffer;
1990e5c31af7Sopenharmony_ci	std::vector<LineSceneSpec::SceneLine>	lines;
1991e5c31af7Sopenharmony_ci
1992e5c31af7Sopenharmony_ci	// supported?
1993e5c31af7Sopenharmony_ci	if (lineWidth <= m_maxLineWidth)
1994e5c31af7Sopenharmony_ci	{
1995e5c31af7Sopenharmony_ci		// generate scene
1996e5c31af7Sopenharmony_ci		generateVertices(m_iteration, drawBuffer, colorBuffer);
1997e5c31af7Sopenharmony_ci		extractLines(lines, drawBuffer, colorBuffer);
1998e5c31af7Sopenharmony_ci
1999e5c31af7Sopenharmony_ci		// log
2000e5c31af7Sopenharmony_ci		{
2001e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "Generated vertices:" << tcu::TestLog::EndMessage;
2002e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)drawBuffer.size(); ++vtxNdx)
2003e5c31af7Sopenharmony_ci				m_testCtx.getLog() << tcu::TestLog::Message << "\t" << drawBuffer[vtxNdx] << ",\tcolor= " << colorBuffer[vtxNdx] << tcu::TestLog::EndMessage;
2004e5c31af7Sopenharmony_ci		}
2005e5c31af7Sopenharmony_ci
2006e5c31af7Sopenharmony_ci		// draw image
2007e5c31af7Sopenharmony_ci		drawPrimitives(resultImage, drawBuffer, colorBuffer, m_primitive);
2008e5c31af7Sopenharmony_ci
2009e5c31af7Sopenharmony_ci		// compare
2010e5c31af7Sopenharmony_ci		{
2011e5c31af7Sopenharmony_ci			RasterizationArguments	args;
2012e5c31af7Sopenharmony_ci			LineSceneSpec			scene;
2013e5c31af7Sopenharmony_ci			LineInterpolationMethod	iterationResult;
2014e5c31af7Sopenharmony_ci
2015e5c31af7Sopenharmony_ci			args.numSamples		= m_numSamples;
2016e5c31af7Sopenharmony_ci			args.subpixelBits	= m_subpixelBits;
2017e5c31af7Sopenharmony_ci			args.redBits		= getPixelFormat().redBits;
2018e5c31af7Sopenharmony_ci			args.greenBits		= getPixelFormat().greenBits;
2019e5c31af7Sopenharmony_ci			args.blueBits		= getPixelFormat().blueBits;
2020e5c31af7Sopenharmony_ci
2021e5c31af7Sopenharmony_ci			scene.lines.swap(lines);
2022e5c31af7Sopenharmony_ci			scene.lineWidth = getLineWidth();
2023e5c31af7Sopenharmony_ci			scene.stippleFactor = 1;
2024e5c31af7Sopenharmony_ci			scene.stipplePattern = 0xFFFF;
2025e5c31af7Sopenharmony_ci			scene.allowNonProjectedInterpolation = true;
2026e5c31af7Sopenharmony_ci
2027e5c31af7Sopenharmony_ci
2028e5c31af7Sopenharmony_ci			iterationResult = verifyLineGroupInterpolation(resultImage, scene, args, m_testCtx.getLog());
2029e5c31af7Sopenharmony_ci			switch (iterationResult)
2030e5c31af7Sopenharmony_ci			{
2031e5c31af7Sopenharmony_ci				case tcu::LINEINTERPOLATION_STRICTLY_CORRECT:
2032e5c31af7Sopenharmony_ci					// line interpolation matches the specification
2033e5c31af7Sopenharmony_ci					m_result.addResult(QP_TEST_RESULT_PASS, "Pass");
2034e5c31af7Sopenharmony_ci					break;
2035e5c31af7Sopenharmony_ci
2036e5c31af7Sopenharmony_ci				case tcu::LINEINTERPOLATION_PROJECTED:
2037e5c31af7Sopenharmony_ci					// line interpolation weights are otherwise correct, but they are projected onto major axis
2038e5c31af7Sopenharmony_ci					m_testCtx.getLog()	<< tcu::TestLog::Message
2039e5c31af7Sopenharmony_ci										<< "Interpolation was calculated using coordinates projected onto major axis. "
2040e5c31af7Sopenharmony_ci										"This method does not produce the same values as the non-projecting method defined in the specification."
2041e5c31af7Sopenharmony_ci										<< tcu::TestLog::EndMessage;
2042e5c31af7Sopenharmony_ci					m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Interpolation was calculated using projected coordinateds");
2043e5c31af7Sopenharmony_ci					break;
2044e5c31af7Sopenharmony_ci
2045e5c31af7Sopenharmony_ci				case tcu::LINEINTERPOLATION_INCORRECT:
2046e5c31af7Sopenharmony_ci					if (scene.lineWidth != 1.0f && m_numSamples > 1)
2047e5c31af7Sopenharmony_ci					{
2048e5c31af7Sopenharmony_ci						// multisampled wide lines might not be supported
2049e5c31af7Sopenharmony_ci						m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Interpolation of multisampled wide lines failed");
2050e5c31af7Sopenharmony_ci					}
2051e5c31af7Sopenharmony_ci					else
2052e5c31af7Sopenharmony_ci					{
2053e5c31af7Sopenharmony_ci						// line interpolation is incorrect
2054e5c31af7Sopenharmony_ci						m_result.addResult(QP_TEST_RESULT_FAIL, "Found invalid pixel values");
2055e5c31af7Sopenharmony_ci					}
2056e5c31af7Sopenharmony_ci					break;
2057e5c31af7Sopenharmony_ci
2058e5c31af7Sopenharmony_ci				default:
2059e5c31af7Sopenharmony_ci					DE_ASSERT(false);
2060e5c31af7Sopenharmony_ci					break;
2061e5c31af7Sopenharmony_ci			}
2062e5c31af7Sopenharmony_ci		}
2063e5c31af7Sopenharmony_ci	}
2064e5c31af7Sopenharmony_ci	else
2065e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Line width " << lineWidth << " not supported, skipping iteration." << tcu::TestLog::EndMessage;
2066e5c31af7Sopenharmony_ci
2067e5c31af7Sopenharmony_ci	// result
2068e5c31af7Sopenharmony_ci	if (++m_iteration == m_iterationCount)
2069e5c31af7Sopenharmony_ci	{
2070e5c31af7Sopenharmony_ci		m_result.setTestContextResult(m_testCtx);
2071e5c31af7Sopenharmony_ci		return STOP;
2072e5c31af7Sopenharmony_ci	}
2073e5c31af7Sopenharmony_ci	else
2074e5c31af7Sopenharmony_ci		return CONTINUE;
2075e5c31af7Sopenharmony_ci}
2076e5c31af7Sopenharmony_ci
2077e5c31af7Sopenharmony_civoid LineInterpolationTest::generateVertices (int iteration, std::vector<tcu::Vec4>& outVertices, std::vector<tcu::Vec4>& outColors) const
2078e5c31af7Sopenharmony_ci{
2079e5c31af7Sopenharmony_ci	// use only red, green and blue
2080e5c31af7Sopenharmony_ci	const tcu::Vec4 colors[] =
2081e5c31af7Sopenharmony_ci	{
2082e5c31af7Sopenharmony_ci		tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2083e5c31af7Sopenharmony_ci		tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2084e5c31af7Sopenharmony_ci		tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
2085e5c31af7Sopenharmony_ci	};
2086e5c31af7Sopenharmony_ci
2087e5c31af7Sopenharmony_ci	de::Random rnd(123 + iteration * 1000 + (int)m_primitive);
2088e5c31af7Sopenharmony_ci
2089e5c31af7Sopenharmony_ci	outVertices.resize(6);
2090e5c31af7Sopenharmony_ci	outColors.resize(6);
2091e5c31af7Sopenharmony_ci
2092e5c31af7Sopenharmony_ci	for (int vtxNdx = 0; vtxNdx < (int)outVertices.size(); ++vtxNdx)
2093e5c31af7Sopenharmony_ci	{
2094e5c31af7Sopenharmony_ci		outVertices[vtxNdx].x() = rnd.getFloat(-0.9f, 0.9f);
2095e5c31af7Sopenharmony_ci		outVertices[vtxNdx].y() = rnd.getFloat(-0.9f, 0.9f);
2096e5c31af7Sopenharmony_ci		outVertices[vtxNdx].z() = 0.0f;
2097e5c31af7Sopenharmony_ci
2098e5c31af7Sopenharmony_ci		if (!m_projective)
2099e5c31af7Sopenharmony_ci			outVertices[vtxNdx].w() = 1.0f;
2100e5c31af7Sopenharmony_ci		else
2101e5c31af7Sopenharmony_ci		{
2102e5c31af7Sopenharmony_ci			const float w = rnd.getFloat(0.2f, 4.0f);
2103e5c31af7Sopenharmony_ci
2104e5c31af7Sopenharmony_ci			outVertices[vtxNdx].x() *= w;
2105e5c31af7Sopenharmony_ci			outVertices[vtxNdx].y() *= w;
2106e5c31af7Sopenharmony_ci			outVertices[vtxNdx].z() *= w;
2107e5c31af7Sopenharmony_ci			outVertices[vtxNdx].w() = w;
2108e5c31af7Sopenharmony_ci		}
2109e5c31af7Sopenharmony_ci
2110e5c31af7Sopenharmony_ci		outColors[vtxNdx] = colors[vtxNdx % DE_LENGTH_OF_ARRAY(colors)];
2111e5c31af7Sopenharmony_ci	}
2112e5c31af7Sopenharmony_ci}
2113e5c31af7Sopenharmony_ci
2114e5c31af7Sopenharmony_civoid LineInterpolationTest::extractLines (std::vector<LineSceneSpec::SceneLine>& outLines, const std::vector<tcu::Vec4>& vertices, const std::vector<tcu::Vec4>& colors) const
2115e5c31af7Sopenharmony_ci{
2116e5c31af7Sopenharmony_ci	switch (m_primitive)
2117e5c31af7Sopenharmony_ci	{
2118e5c31af7Sopenharmony_ci		case GL_LINES:
2119e5c31af7Sopenharmony_ci		{
2120e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; vtxNdx += 2)
2121e5c31af7Sopenharmony_ci			{
2122e5c31af7Sopenharmony_ci				LineSceneSpec::SceneLine line;
2123e5c31af7Sopenharmony_ci				line.positions[0] = vertices[vtxNdx + 0];
2124e5c31af7Sopenharmony_ci				line.positions[1] = vertices[vtxNdx + 1];
2125e5c31af7Sopenharmony_ci
2126e5c31af7Sopenharmony_ci				if (m_flatshade)
2127e5c31af7Sopenharmony_ci				{
2128e5c31af7Sopenharmony_ci					line.colors[0] = colors[vtxNdx + 1];
2129e5c31af7Sopenharmony_ci					line.colors[1] = colors[vtxNdx + 1];
2130e5c31af7Sopenharmony_ci				}
2131e5c31af7Sopenharmony_ci				else
2132e5c31af7Sopenharmony_ci				{
2133e5c31af7Sopenharmony_ci					line.colors[0] = colors[vtxNdx + 0];
2134e5c31af7Sopenharmony_ci					line.colors[1] = colors[vtxNdx + 1];
2135e5c31af7Sopenharmony_ci				}
2136e5c31af7Sopenharmony_ci
2137e5c31af7Sopenharmony_ci				outLines.push_back(line);
2138e5c31af7Sopenharmony_ci			}
2139e5c31af7Sopenharmony_ci			break;
2140e5c31af7Sopenharmony_ci		}
2141e5c31af7Sopenharmony_ci
2142e5c31af7Sopenharmony_ci		case GL_LINE_STRIP:
2143e5c31af7Sopenharmony_ci		{
2144e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)vertices.size() - 1; ++vtxNdx)
2145e5c31af7Sopenharmony_ci			{
2146e5c31af7Sopenharmony_ci				LineSceneSpec::SceneLine line;
2147e5c31af7Sopenharmony_ci				line.positions[0] = vertices[vtxNdx + 0];
2148e5c31af7Sopenharmony_ci				line.positions[1] = vertices[vtxNdx + 1];
2149e5c31af7Sopenharmony_ci
2150e5c31af7Sopenharmony_ci				if (m_flatshade)
2151e5c31af7Sopenharmony_ci				{
2152e5c31af7Sopenharmony_ci					line.colors[0] = colors[vtxNdx + 1];
2153e5c31af7Sopenharmony_ci					line.colors[1] = colors[vtxNdx + 1];
2154e5c31af7Sopenharmony_ci				}
2155e5c31af7Sopenharmony_ci				else
2156e5c31af7Sopenharmony_ci				{
2157e5c31af7Sopenharmony_ci					line.colors[0] = colors[vtxNdx + 0];
2158e5c31af7Sopenharmony_ci					line.colors[1] = colors[vtxNdx + 1];
2159e5c31af7Sopenharmony_ci				}
2160e5c31af7Sopenharmony_ci
2161e5c31af7Sopenharmony_ci				outLines.push_back(line);
2162e5c31af7Sopenharmony_ci			}
2163e5c31af7Sopenharmony_ci			break;
2164e5c31af7Sopenharmony_ci		}
2165e5c31af7Sopenharmony_ci
2166e5c31af7Sopenharmony_ci		case GL_LINE_LOOP:
2167e5c31af7Sopenharmony_ci		{
2168e5c31af7Sopenharmony_ci			for (int vtxNdx = 0; vtxNdx < (int)vertices.size(); ++vtxNdx)
2169e5c31af7Sopenharmony_ci			{
2170e5c31af7Sopenharmony_ci				LineSceneSpec::SceneLine line;
2171e5c31af7Sopenharmony_ci				line.positions[0] = vertices[(vtxNdx + 0) % (int)vertices.size()];
2172e5c31af7Sopenharmony_ci				line.positions[1] = vertices[(vtxNdx + 1) % (int)vertices.size()];
2173e5c31af7Sopenharmony_ci
2174e5c31af7Sopenharmony_ci				if (m_flatshade)
2175e5c31af7Sopenharmony_ci				{
2176e5c31af7Sopenharmony_ci					line.colors[0] = colors[(vtxNdx + 1) % (int)vertices.size()];
2177e5c31af7Sopenharmony_ci					line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()];
2178e5c31af7Sopenharmony_ci				}
2179e5c31af7Sopenharmony_ci				else
2180e5c31af7Sopenharmony_ci				{
2181e5c31af7Sopenharmony_ci					line.colors[0] = colors[(vtxNdx + 0) % (int)vertices.size()];
2182e5c31af7Sopenharmony_ci					line.colors[1] = colors[(vtxNdx + 1) % (int)vertices.size()];
2183e5c31af7Sopenharmony_ci				}
2184e5c31af7Sopenharmony_ci
2185e5c31af7Sopenharmony_ci				outLines.push_back(line);
2186e5c31af7Sopenharmony_ci			}
2187e5c31af7Sopenharmony_ci			break;
2188e5c31af7Sopenharmony_ci		}
2189e5c31af7Sopenharmony_ci
2190e5c31af7Sopenharmony_ci		default:
2191e5c31af7Sopenharmony_ci			DE_ASSERT(false);
2192e5c31af7Sopenharmony_ci	}
2193e5c31af7Sopenharmony_ci}
2194e5c31af7Sopenharmony_ci
2195e5c31af7Sopenharmony_cifloat LineInterpolationTest::getLineWidth (void) const
2196e5c31af7Sopenharmony_ci{
2197e5c31af7Sopenharmony_ci	return m_lineWidths[m_iteration];
2198e5c31af7Sopenharmony_ci}
2199e5c31af7Sopenharmony_ci
2200e5c31af7Sopenharmony_ci} // anonymous
2201e5c31af7Sopenharmony_ci
2202e5c31af7Sopenharmony_ciRasterizationTests::RasterizationTests (Context& context)
2203e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "rasterization", "Rasterization Tests")
2204e5c31af7Sopenharmony_ci{
2205e5c31af7Sopenharmony_ci}
2206e5c31af7Sopenharmony_ci
2207e5c31af7Sopenharmony_ciRasterizationTests::~RasterizationTests (void)
2208e5c31af7Sopenharmony_ci{
2209e5c31af7Sopenharmony_ci}
2210e5c31af7Sopenharmony_ci
2211e5c31af7Sopenharmony_civoid RasterizationTests::init (void)
2212e5c31af7Sopenharmony_ci{
2213e5c31af7Sopenharmony_ci	// .primitives
2214e5c31af7Sopenharmony_ci	{
2215e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* const primitives = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization");
2216e5c31af7Sopenharmony_ci
2217e5c31af7Sopenharmony_ci		addChild(primitives);
2218e5c31af7Sopenharmony_ci
2219e5c31af7Sopenharmony_ci		primitives->addChild(new TrianglesCase		(m_context, "triangles",		"Render primitives as GL_TRIANGLES, verify rasterization result"));
2220e5c31af7Sopenharmony_ci		primitives->addChild(new TriangleStripCase	(m_context, "triangle_strip",	"Render primitives as GL_TRIANGLE_STRIP, verify rasterization result"));
2221e5c31af7Sopenharmony_ci		primitives->addChild(new TriangleFanCase	(m_context, "triangle_fan",		"Render primitives as GL_TRIANGLE_FAN, verify rasterization result"));
2222e5c31af7Sopenharmony_ci		primitives->addChild(new LinesCase			(m_context, "lines",			"Render primitives as GL_LINES, verify rasterization result",							PRIMITIVEWIDENESS_NARROW));
2223e5c31af7Sopenharmony_ci		primitives->addChild(new LineStripCase		(m_context, "line_strip",		"Render primitives as GL_LINE_STRIP, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
2224e5c31af7Sopenharmony_ci		primitives->addChild(new LineLoopCase		(m_context, "line_loop",		"Render primitives as GL_LINE_LOOP, verify rasterization result",						PRIMITIVEWIDENESS_NARROW));
2225e5c31af7Sopenharmony_ci		primitives->addChild(new LinesCase			(m_context, "lines_wide",		"Render primitives as GL_LINES with wide lines, verify rasterization result",			PRIMITIVEWIDENESS_WIDE));
2226e5c31af7Sopenharmony_ci		primitives->addChild(new LineStripCase		(m_context, "line_strip_wide",	"Render primitives as GL_LINE_STRIP with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE));
2227e5c31af7Sopenharmony_ci		primitives->addChild(new LineLoopCase		(m_context, "line_loop_wide",	"Render primitives as GL_LINE_LOOP with wide lines, verify rasterization result",		PRIMITIVEWIDENESS_WIDE));
2228e5c31af7Sopenharmony_ci		primitives->addChild(new PointCase			(m_context, "points",			"Render primitives as GL_POINTS, verify rasterization result",							PRIMITIVEWIDENESS_WIDE));
2229e5c31af7Sopenharmony_ci	}
2230e5c31af7Sopenharmony_ci
2231e5c31af7Sopenharmony_ci	// .fill_rules
2232e5c31af7Sopenharmony_ci	{
2233e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules");
2234e5c31af7Sopenharmony_ci
2235e5c31af7Sopenharmony_ci		addChild(fillRules);
2236e5c31af7Sopenharmony_ci
2237e5c31af7Sopenharmony_ci		fillRules->addChild(new FillRuleCase(m_context,	"basic_quad",			"Verify fill rules",	FillRuleCase::FILLRULECASE_BASIC));
2238e5c31af7Sopenharmony_ci		fillRules->addChild(new FillRuleCase(m_context,	"basic_quad_reverse",	"Verify fill rules",	FillRuleCase::FILLRULECASE_REVERSED));
2239e5c31af7Sopenharmony_ci		fillRules->addChild(new FillRuleCase(m_context,	"clipped_full",			"Verify fill rules",	FillRuleCase::FILLRULECASE_CLIPPED_FULL));
2240e5c31af7Sopenharmony_ci		fillRules->addChild(new FillRuleCase(m_context,	"clipped_partly",		"Verify fill rules",	FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL));
2241e5c31af7Sopenharmony_ci		fillRules->addChild(new FillRuleCase(m_context,	"projected",			"Verify fill rules",	FillRuleCase::FILLRULECASE_PROJECTED));
2242e5c31af7Sopenharmony_ci	}
2243e5c31af7Sopenharmony_ci
2244e5c31af7Sopenharmony_ci	// .culling
2245e5c31af7Sopenharmony_ci	{
2246e5c31af7Sopenharmony_ci		static const struct CullMode
2247e5c31af7Sopenharmony_ci		{
2248e5c31af7Sopenharmony_ci			glw::GLenum	mode;
2249e5c31af7Sopenharmony_ci			const char*	prefix;
2250e5c31af7Sopenharmony_ci		} cullModes[] =
2251e5c31af7Sopenharmony_ci		{
2252e5c31af7Sopenharmony_ci			{ GL_FRONT,				"front_"	},
2253e5c31af7Sopenharmony_ci			{ GL_BACK,				"back_"		},
2254e5c31af7Sopenharmony_ci			{ GL_FRONT_AND_BACK,	"both_"		},
2255e5c31af7Sopenharmony_ci		};
2256e5c31af7Sopenharmony_ci		static const struct PrimitiveType
2257e5c31af7Sopenharmony_ci		{
2258e5c31af7Sopenharmony_ci			glw::GLenum	type;
2259e5c31af7Sopenharmony_ci			const char*	name;
2260e5c31af7Sopenharmony_ci		} primitiveTypes[] =
2261e5c31af7Sopenharmony_ci		{
2262e5c31af7Sopenharmony_ci			{ GL_TRIANGLES,			"triangles"			},
2263e5c31af7Sopenharmony_ci			{ GL_TRIANGLE_STRIP,	"triangle_strip"	},
2264e5c31af7Sopenharmony_ci			{ GL_TRIANGLE_FAN,		"triangle_fan"		},
2265e5c31af7Sopenharmony_ci		};
2266e5c31af7Sopenharmony_ci		static const struct FrontFaceOrder
2267e5c31af7Sopenharmony_ci		{
2268e5c31af7Sopenharmony_ci			glw::GLenum	mode;
2269e5c31af7Sopenharmony_ci			const char*	postfix;
2270e5c31af7Sopenharmony_ci		} frontOrders[] =
2271e5c31af7Sopenharmony_ci		{
2272e5c31af7Sopenharmony_ci			{ GL_CCW,	""			},
2273e5c31af7Sopenharmony_ci			{ GL_CW,	"_reverse"	},
2274e5c31af7Sopenharmony_ci		};
2275e5c31af7Sopenharmony_ci
2276e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* const culling = new tcu::TestCaseGroup(m_testCtx, "culling", "Culling");
2277e5c31af7Sopenharmony_ci
2278e5c31af7Sopenharmony_ci		addChild(culling);
2279e5c31af7Sopenharmony_ci
2280e5c31af7Sopenharmony_ci		for (int cullModeNdx   = 0; cullModeNdx   < DE_LENGTH_OF_ARRAY(cullModes);      ++cullModeNdx)
2281e5c31af7Sopenharmony_ci		for (int primitiveNdx  = 0; primitiveNdx  < DE_LENGTH_OF_ARRAY(primitiveTypes); ++primitiveNdx)
2282e5c31af7Sopenharmony_ci		for (int frontOrderNdx = 0; frontOrderNdx < DE_LENGTH_OF_ARRAY(frontOrders);    ++frontOrderNdx)
2283e5c31af7Sopenharmony_ci		{
2284e5c31af7Sopenharmony_ci			const std::string name = std::string(cullModes[cullModeNdx].prefix) + primitiveTypes[primitiveNdx].name + frontOrders[frontOrderNdx].postfix;
2285e5c31af7Sopenharmony_ci
2286e5c31af7Sopenharmony_ci			culling->addChild(new CullingTest(m_context, name.c_str(), "Test primitive culling.", cullModes[cullModeNdx].mode, primitiveTypes[primitiveNdx].type, frontOrders[frontOrderNdx].mode));
2287e5c31af7Sopenharmony_ci		}
2288e5c31af7Sopenharmony_ci	}
2289e5c31af7Sopenharmony_ci
2290e5c31af7Sopenharmony_ci	// .interpolation
2291e5c31af7Sopenharmony_ci	{
2292e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Test interpolation");
2293e5c31af7Sopenharmony_ci
2294e5c31af7Sopenharmony_ci		addChild(interpolation);
2295e5c31af7Sopenharmony_ci
2296e5c31af7Sopenharmony_ci		// .basic
2297e5c31af7Sopenharmony_ci		{
2298e5c31af7Sopenharmony_ci			tcu::TestCaseGroup* const basic = new tcu::TestCaseGroup(m_testCtx, "basic", "Non-projective interpolation");
2299e5c31af7Sopenharmony_ci
2300e5c31af7Sopenharmony_ci			interpolation->addChild(basic);
2301e5c31af7Sopenharmony_ci
2302e5c31af7Sopenharmony_ci			basic->addChild(new TriangleInterpolationTest		(m_context, "triangles",		"Verify triangle interpolation",		GL_TRIANGLES,		INTERPOLATIONFLAGS_NONE));
2303e5c31af7Sopenharmony_ci			basic->addChild(new TriangleInterpolationTest		(m_context, "triangle_strip",	"Verify triangle strip interpolation",	GL_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_NONE));
2304e5c31af7Sopenharmony_ci			basic->addChild(new TriangleInterpolationTest		(m_context, "triangle_fan",		"Verify triangle fan interpolation",	GL_TRIANGLE_FAN,	INTERPOLATIONFLAGS_NONE));
2305e5c31af7Sopenharmony_ci			basic->addChild(new LineInterpolationTest			(m_context, "lines",			"Verify line interpolation",			GL_LINES,			INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW));
2306e5c31af7Sopenharmony_ci			basic->addChild(new LineInterpolationTest			(m_context, "line_strip",		"Verify line strip interpolation",		GL_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW));
2307e5c31af7Sopenharmony_ci			basic->addChild(new LineInterpolationTest			(m_context, "line_loop",		"Verify line loop interpolation",		GL_LINE_LOOP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW));
2308e5c31af7Sopenharmony_ci			basic->addChild(new LineInterpolationTest			(m_context, "lines_wide",		"Verify wide line interpolation",		GL_LINES,			INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE));
2309e5c31af7Sopenharmony_ci			basic->addChild(new LineInterpolationTest			(m_context, "line_strip_wide",	"Verify wide line strip interpolation",	GL_LINE_STRIP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE));
2310e5c31af7Sopenharmony_ci			basic->addChild(new LineInterpolationTest			(m_context, "line_loop_wide",	"Verify wide line loop interpolation",	GL_LINE_LOOP,		INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE));
2311e5c31af7Sopenharmony_ci		}
2312e5c31af7Sopenharmony_ci
2313e5c31af7Sopenharmony_ci		// .projected
2314e5c31af7Sopenharmony_ci		{
2315e5c31af7Sopenharmony_ci			tcu::TestCaseGroup* const projected = new tcu::TestCaseGroup(m_testCtx, "projected", "Projective interpolation");
2316e5c31af7Sopenharmony_ci
2317e5c31af7Sopenharmony_ci			interpolation->addChild(projected);
2318e5c31af7Sopenharmony_ci
2319e5c31af7Sopenharmony_ci			projected->addChild(new TriangleInterpolationTest	(m_context, "triangles",		"Verify triangle interpolation",		GL_TRIANGLES,		INTERPOLATIONFLAGS_PROJECTED));
2320e5c31af7Sopenharmony_ci			projected->addChild(new TriangleInterpolationTest	(m_context, "triangle_strip",	"Verify triangle strip interpolation",	GL_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_PROJECTED));
2321e5c31af7Sopenharmony_ci			projected->addChild(new TriangleInterpolationTest	(m_context, "triangle_fan",		"Verify triangle fan interpolation",	GL_TRIANGLE_FAN,	INTERPOLATIONFLAGS_PROJECTED));
2322e5c31af7Sopenharmony_ci			projected->addChild(new LineInterpolationTest		(m_context, "lines",			"Verify line interpolation",			GL_LINES,			INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW));
2323e5c31af7Sopenharmony_ci			projected->addChild(new LineInterpolationTest		(m_context, "line_strip",		"Verify line strip interpolation",		GL_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW));
2324e5c31af7Sopenharmony_ci			projected->addChild(new LineInterpolationTest		(m_context, "line_loop",		"Verify line loop interpolation",		GL_LINE_LOOP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_NARROW));
2325e5c31af7Sopenharmony_ci			projected->addChild(new LineInterpolationTest		(m_context, "lines_wide",		"Verify wide line interpolation",		GL_LINES,			INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE));
2326e5c31af7Sopenharmony_ci			projected->addChild(new LineInterpolationTest		(m_context, "line_strip_wide",	"Verify wide line strip interpolation",	GL_LINE_STRIP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE));
2327e5c31af7Sopenharmony_ci			projected->addChild(new LineInterpolationTest		(m_context, "line_loop_wide",	"Verify wide line loop interpolation",	GL_LINE_LOOP,		INTERPOLATIONFLAGS_PROJECTED,	PRIMITIVEWIDENESS_WIDE));
2328e5c31af7Sopenharmony_ci		}
2329e5c31af7Sopenharmony_ci	}
2330e5c31af7Sopenharmony_ci
2331e5c31af7Sopenharmony_ci	// .flatshading
2332e5c31af7Sopenharmony_ci	{
2333e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* const flatshading = new tcu::TestCaseGroup(m_testCtx, "flatshading", "Test flatshading");
2334e5c31af7Sopenharmony_ci
2335e5c31af7Sopenharmony_ci		addChild(flatshading);
2336e5c31af7Sopenharmony_ci
2337e5c31af7Sopenharmony_ci		flatshading->addChild(new TriangleInterpolationTest		(m_context, "triangles",		"Verify triangle flatshading",			GL_TRIANGLES,		INTERPOLATIONFLAGS_FLATSHADE));
2338e5c31af7Sopenharmony_ci		flatshading->addChild(new TriangleInterpolationTest		(m_context, "triangle_strip",	"Verify triangle strip flatshading",	GL_TRIANGLE_STRIP,	INTERPOLATIONFLAGS_FLATSHADE));
2339e5c31af7Sopenharmony_ci		flatshading->addChild(new TriangleInterpolationTest		(m_context, "triangle_fan",		"Verify triangle fan flatshading",		GL_TRIANGLE_FAN,	INTERPOLATIONFLAGS_FLATSHADE));
2340e5c31af7Sopenharmony_ci		flatshading->addChild(new LineInterpolationTest			(m_context, "lines",			"Verify line flatshading",				GL_LINES,			INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW));
2341e5c31af7Sopenharmony_ci		flatshading->addChild(new LineInterpolationTest			(m_context, "line_strip",		"Verify line strip flatshading",		GL_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW));
2342e5c31af7Sopenharmony_ci		flatshading->addChild(new LineInterpolationTest			(m_context, "line_loop",		"Verify line loop flatshading",			GL_LINE_LOOP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_NARROW));
2343e5c31af7Sopenharmony_ci		flatshading->addChild(new LineInterpolationTest			(m_context, "lines_wide",		"Verify wide line flatshading",			GL_LINES,			INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE));
2344e5c31af7Sopenharmony_ci		flatshading->addChild(new LineInterpolationTest			(m_context, "line_strip_wide",	"Verify wide line strip flatshading",	GL_LINE_STRIP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE));
2345e5c31af7Sopenharmony_ci		flatshading->addChild(new LineInterpolationTest			(m_context, "line_loop_wide",	"Verify wide line loop flatshading",	GL_LINE_LOOP,		INTERPOLATIONFLAGS_FLATSHADE,	PRIMITIVEWIDENESS_WIDE));
2346e5c31af7Sopenharmony_ci	}
2347e5c31af7Sopenharmony_ci
2348e5c31af7Sopenharmony_ci	// .fbo
2349e5c31af7Sopenharmony_ci	{
2350e5c31af7Sopenharmony_ci		static const struct
2351e5c31af7Sopenharmony_ci		{
2352e5c31af7Sopenharmony_ci			const char*						name;
2353e5c31af7Sopenharmony_ci			BaseRenderingCase::RenderTarget	target;
2354e5c31af7Sopenharmony_ci			int								numSamples;
2355e5c31af7Sopenharmony_ci		} renderTargets[] =
2356e5c31af7Sopenharmony_ci		{
2357e5c31af7Sopenharmony_ci			{ "texture_2d",				BaseRenderingCase::RENDERTARGET_TEXTURE_2D,			-1									},
2358e5c31af7Sopenharmony_ci			{ "rbo_singlesample",		BaseRenderingCase::RENDERTARGET_RBO_SINGLESAMPLE,	-1									},
2359e5c31af7Sopenharmony_ci			{ "rbo_multisample_4",		BaseRenderingCase::RENDERTARGET_RBO_MULTISAMPLE,	4									},
2360e5c31af7Sopenharmony_ci			{ "rbo_multisample_max",	BaseRenderingCase::RENDERTARGET_RBO_MULTISAMPLE,	BaseRenderingCase::SAMPLE_COUNT_MAX	},
2361e5c31af7Sopenharmony_ci		};
2362e5c31af7Sopenharmony_ci
2363e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* const fboGroup = new tcu::TestCaseGroup(m_testCtx, "fbo", "Test using framebuffer objects");
2364e5c31af7Sopenharmony_ci		addChild(fboGroup);
2365e5c31af7Sopenharmony_ci
2366e5c31af7Sopenharmony_ci		// .texture_2d
2367e5c31af7Sopenharmony_ci		// .rbo_singlesample
2368e5c31af7Sopenharmony_ci		// .rbo_multisample_4
2369e5c31af7Sopenharmony_ci		// .rbo_multisample_max
2370e5c31af7Sopenharmony_ci		for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(renderTargets); ++targetNdx)
2371e5c31af7Sopenharmony_ci		{
2372e5c31af7Sopenharmony_ci			tcu::TestCaseGroup* const colorAttachmentGroup = new tcu::TestCaseGroup(m_testCtx, renderTargets[targetNdx].name, ("Test using " + std::string(renderTargets[targetNdx].name) + " color attachment").c_str());
2373e5c31af7Sopenharmony_ci			fboGroup->addChild(colorAttachmentGroup);
2374e5c31af7Sopenharmony_ci
2375e5c31af7Sopenharmony_ci			// .primitives
2376e5c31af7Sopenharmony_ci			{
2377e5c31af7Sopenharmony_ci				tcu::TestCaseGroup* const primitiveGroup = new tcu::TestCaseGroup(m_testCtx, "primitives", "Primitive rasterization");
2378e5c31af7Sopenharmony_ci				colorAttachmentGroup->addChild(primitiveGroup);
2379e5c31af7Sopenharmony_ci
2380e5c31af7Sopenharmony_ci				primitiveGroup->addChild(new TrianglesCase	(m_context, "triangles",	"Render primitives as GL_TRIANGLES, verify rasterization result",											renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2381e5c31af7Sopenharmony_ci				primitiveGroup->addChild(new LinesCase		(m_context, "lines",		"Render primitives as GL_LINES, verify rasterization result",					PRIMITIVEWIDENESS_NARROW,	renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2382e5c31af7Sopenharmony_ci				primitiveGroup->addChild(new LinesCase		(m_context, "lines_wide",	"Render primitives as GL_LINES with wide lines, verify rasterization result",	PRIMITIVEWIDENESS_WIDE,		renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2383e5c31af7Sopenharmony_ci				primitiveGroup->addChild(new PointCase		(m_context, "points",		"Render primitives as GL_POINTS, verify rasterization result",					PRIMITIVEWIDENESS_WIDE,		renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2384e5c31af7Sopenharmony_ci			}
2385e5c31af7Sopenharmony_ci
2386e5c31af7Sopenharmony_ci			// .fill_rules
2387e5c31af7Sopenharmony_ci			{
2388e5c31af7Sopenharmony_ci				tcu::TestCaseGroup* const fillRules = new tcu::TestCaseGroup(m_testCtx, "fill_rules", "Primitive fill rules");
2389e5c31af7Sopenharmony_ci
2390e5c31af7Sopenharmony_ci				colorAttachmentGroup->addChild(fillRules);
2391e5c31af7Sopenharmony_ci
2392e5c31af7Sopenharmony_ci				fillRules->addChild(new FillRuleCase(m_context,	"basic_quad",			"Verify fill rules",	FillRuleCase::FILLRULECASE_BASIC,			renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2393e5c31af7Sopenharmony_ci				fillRules->addChild(new FillRuleCase(m_context,	"basic_quad_reverse",	"Verify fill rules",	FillRuleCase::FILLRULECASE_REVERSED,		renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2394e5c31af7Sopenharmony_ci				fillRules->addChild(new FillRuleCase(m_context,	"clipped_full",			"Verify fill rules",	FillRuleCase::FILLRULECASE_CLIPPED_FULL,	renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2395e5c31af7Sopenharmony_ci				fillRules->addChild(new FillRuleCase(m_context,	"clipped_partly",		"Verify fill rules",	FillRuleCase::FILLRULECASE_CLIPPED_PARTIAL,	renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2396e5c31af7Sopenharmony_ci				fillRules->addChild(new FillRuleCase(m_context,	"projected",			"Verify fill rules",	FillRuleCase::FILLRULECASE_PROJECTED,		renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2397e5c31af7Sopenharmony_ci			}
2398e5c31af7Sopenharmony_ci
2399e5c31af7Sopenharmony_ci			// .interpolation
2400e5c31af7Sopenharmony_ci			{
2401e5c31af7Sopenharmony_ci				tcu::TestCaseGroup* const interpolation = new tcu::TestCaseGroup(m_testCtx, "interpolation", "Non-projective interpolation");
2402e5c31af7Sopenharmony_ci
2403e5c31af7Sopenharmony_ci				colorAttachmentGroup->addChild(interpolation);
2404e5c31af7Sopenharmony_ci
2405e5c31af7Sopenharmony_ci				interpolation->addChild(new TriangleInterpolationTest		(m_context, "triangles",		"Verify triangle interpolation",		GL_TRIANGLES,		INTERPOLATIONFLAGS_NONE,								renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2406e5c31af7Sopenharmony_ci				interpolation->addChild(new LineInterpolationTest			(m_context, "lines",			"Verify line interpolation",			GL_LINES,			INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_NARROW,	renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2407e5c31af7Sopenharmony_ci				interpolation->addChild(new LineInterpolationTest			(m_context, "lines_wide",		"Verify wide line interpolation",		GL_LINES,			INTERPOLATIONFLAGS_NONE,	PRIMITIVEWIDENESS_WIDE,		renderTargets[targetNdx].target, renderTargets[targetNdx].numSamples));
2408e5c31af7Sopenharmony_ci			}
2409e5c31af7Sopenharmony_ci		}
2410e5c31af7Sopenharmony_ci	}
2411e5c31af7Sopenharmony_ci}
2412e5c31af7Sopenharmony_ci
2413e5c31af7Sopenharmony_ci} // Functional
2414e5c31af7Sopenharmony_ci} // gles3
2415e5c31af7Sopenharmony_ci} // deqp
2416