1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
3e5c31af7Sopenharmony_ci * -----------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "esextcTessellationShaderIsolines.hpp"
25e5c31af7Sopenharmony_ci#include "esextcTessellationShaderUtils.hpp"
26e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
27e5c31af7Sopenharmony_ci#include "gluDefs.hpp"
28e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
29e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
30e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_cinamespace glcts
33e5c31af7Sopenharmony_ci{
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ci/** Constructor
36e5c31af7Sopenharmony_ci *
37e5c31af7Sopenharmony_ci * @param context Test context
38e5c31af7Sopenharmony_ci **/
39e5c31af7Sopenharmony_ciTessellationShadersIsolines::TessellationShadersIsolines(Context& context, const ExtParameters& extParams)
40e5c31af7Sopenharmony_ci	: TestCaseBase(context, extParams, "isolines_tessellation",
41e5c31af7Sopenharmony_ci				   "Verifies that the number of isolines generated during tessellation is "
42e5c31af7Sopenharmony_ci				   "derived from the first outer tessellation level.\n"
43e5c31af7Sopenharmony_ci				   "Makes sure that the number of segments in each isoline is derived from "
44e5c31af7Sopenharmony_ci				   "the second outer tessellation level.\n"
45e5c31af7Sopenharmony_ci				   "Makes sure that both inner tessellation levels and the 3rd and the 4th "
46e5c31af7Sopenharmony_ci				   "outer tessellation levels do not affect the tessellation process.\n"
47e5c31af7Sopenharmony_ci				   "Makes sure that equal_spacing vertex spacing mode does not affect amount"
48e5c31af7Sopenharmony_ci				   " of generated isolines.\n"
49e5c31af7Sopenharmony_ci				   "Makes sure no line is drawn between (0, 1) and (1, 1) in (u, v) domain.")
50e5c31af7Sopenharmony_ci	, m_irrelevant_tess_value_1(0.0f)
51e5c31af7Sopenharmony_ci	, m_irrelevant_tess_value_2(0.0f)
52e5c31af7Sopenharmony_ci	, m_utils_ptr(DE_NULL)
53e5c31af7Sopenharmony_ci	, m_vao_id(0)
54e5c31af7Sopenharmony_ci{
55e5c31af7Sopenharmony_ci	/* Left blank on purpose */
56e5c31af7Sopenharmony_ci}
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_ci/** Checks that amount of isolines generated during tessellation corresponds to the
59e5c31af7Sopenharmony_ci *  first outer tessellation level.
60e5c31af7Sopenharmony_ci *
61e5c31af7Sopenharmony_ci *  This check needs not to operate over all test results generated for a particular
62e5c31af7Sopenharmony_ci *  vertex spacing mode.
63e5c31af7Sopenharmony_ci *
64e5c31af7Sopenharmony_ci *  @param test_result Value of MAX_TESS_GEN_LEVEL token. For ES3.1 it will be equal to
65e5c31af7Sopenharmony_ci *                     GL_MAX_TESS_GEN_LEVEL_EXT and for ES3.2 to GL_MAX_TESS_GEN_LEVEL.
66e5c31af7Sopenharmony_ci *
67e5c31af7Sopenharmony_ci **/
68e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkFirstOuterTessellationLevelEffect(_test_result&	 test_result,
69e5c31af7Sopenharmony_ci																		 const glw::GLenum glMaxTessGenLevelToken)
70e5c31af7Sopenharmony_ci{
71e5c31af7Sopenharmony_ci	glcts::Context&		  context					  = test_result.parent->parent->getContext();
72e5c31af7Sopenharmony_ci	const glw::Functions& gl						  = context.getRenderContext().getFunctions();
73e5c31af7Sopenharmony_ci	glw::GLint			  gl_max_tess_gen_level_value = 0;
74e5c31af7Sopenharmony_ci	unsigned int		  n_isolines_expected		  = 0;
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ci	if (test_result.n_vertices != 0)
77e5c31af7Sopenharmony_ci	{
78e5c31af7Sopenharmony_ci		/* Calculate how many isolines we're expecting */
79e5c31af7Sopenharmony_ci		gl.getIntegerv(glMaxTessGenLevelToken, &gl_max_tess_gen_level_value);
80e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci		/* NOTE: Amount of isolines should always be based on TESSELLATION_SHADER_VERTEX_SPACING_EQUAL
83e5c31af7Sopenharmony_ci		 *       vertex spacing mode, even if a different one is defined in TE stage.
84e5c31af7Sopenharmony_ci		 */
85e5c31af7Sopenharmony_ci		float outer_zero_tess_level_clamped_rounded = 0.0f;
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ci		TessellationShaderUtils::getTessellationLevelAfterVertexSpacing(
88e5c31af7Sopenharmony_ci			TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, test_result.parent->outer_tess_levels[0],
89e5c31af7Sopenharmony_ci			gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */
90e5c31af7Sopenharmony_ci			&outer_zero_tess_level_clamped_rounded);
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ci		n_isolines_expected = (unsigned int)outer_zero_tess_level_clamped_rounded;
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci		if (test_result.n_isolines != n_isolines_expected)
95e5c31af7Sopenharmony_ci		{
96e5c31af7Sopenharmony_ci			tcu::TestContext& test = test_result.parent->parent->getTestContext();
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ci			test.getLog() << tcu::TestLog::Message
99e5c31af7Sopenharmony_ci						  << "Tessellator generated an invalid amount of isolines:" << test_result.n_isolines
100e5c31af7Sopenharmony_ci						  << " instead of the expected amount:" << n_isolines_expected
101e5c31af7Sopenharmony_ci						  << " for the following inner tessellation level configuration:"
102e5c31af7Sopenharmony_ci						  << " (" << test_result.parent->inner_tess_levels[0] << ", "
103e5c31af7Sopenharmony_ci						  << test_result.parent->inner_tess_levels[1] << ")"
104e5c31af7Sopenharmony_ci						  << " and the following outer tesellation level configuration:"
105e5c31af7Sopenharmony_ci						  << " (" << test_result.parent->outer_tess_levels[0] << ", "
106e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[1] << ", "
107e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[2] << ", "
108e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[3] << ")" << tcu::TestLog::EndMessage;
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid amount of isolines generated by tessellator");
111e5c31af7Sopenharmony_ci		}
112e5c31af7Sopenharmony_ci	} /* if (test_run.n_vertices != 0) */
113e5c31af7Sopenharmony_ci}
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ci/** Makes sure that tessellation coordinates generated for inner+outer tessellation level
116e5c31af7Sopenharmony_ci *  configurations, between which irrelevant levels have been defined, are exactly the same.
117e5c31af7Sopenharmony_ci *
118e5c31af7Sopenharmony_ci *  This check needs to operate over all test results generated for a particular
119e5c31af7Sopenharmony_ci *  vertex spacing mode.
120e5c31af7Sopenharmony_ci *
121e5c31af7Sopenharmony_ci *  This function throws a TestError exception if the check fails.
122e5c31af7Sopenharmony_ci **/
123e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkIrrelevantTessellationLevelsHaveNoEffect()
124e5c31af7Sopenharmony_ci{
125e5c31af7Sopenharmony_ci	/* Make sure that two example data sets, for which irrelevant tessellation levels have
126e5c31af7Sopenharmony_ci	 * been changed, are exactly the same
127e5c31af7Sopenharmony_ci	 */
128e5c31af7Sopenharmony_ci	DE_ASSERT(m_test_results.find(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL) != m_test_results.end());
129e5c31af7Sopenharmony_ci
130e5c31af7Sopenharmony_ci	const float			   epsilon								  = 1e-5f;
131e5c31af7Sopenharmony_ci	float				   irrelevant_tess_level1_rounded_clamped = 0.0f;
132e5c31af7Sopenharmony_ci	int					   irrelevant_tess_level1				  = 0;
133e5c31af7Sopenharmony_ci	float				   irrelevant_tess_level2_rounded_clamped = 0.0f;
134e5c31af7Sopenharmony_ci	int					   irrelevant_tess_level2				  = 0;
135e5c31af7Sopenharmony_ci	_test_results_iterator test_result_iterator_start =
136e5c31af7Sopenharmony_ci		m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].begin();
137e5c31af7Sopenharmony_ci	_test_results_iterator test_result_iterator_end = m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].end();
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_ci	/* Calculate two tessellation level values that we've used in init() */
140e5c31af7Sopenharmony_ci	const glw::Functions& gl						  = m_context.getRenderContext().getFunctions();
141e5c31af7Sopenharmony_ci	glw::GLint			  gl_max_tess_gen_level_value = 0;
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ci	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
144e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ci	TessellationShaderUtils::getTessellationLevelAfterVertexSpacing(
147e5c31af7Sopenharmony_ci		TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, m_irrelevant_tess_value_1, gl_max_tess_gen_level_value,
148e5c31af7Sopenharmony_ci		DE_NULL, /* out_clamped */
149e5c31af7Sopenharmony_ci		&irrelevant_tess_level1_rounded_clamped);
150e5c31af7Sopenharmony_ci	TessellationShaderUtils::getTessellationLevelAfterVertexSpacing(
151e5c31af7Sopenharmony_ci		TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, m_irrelevant_tess_value_2, gl_max_tess_gen_level_value,
152e5c31af7Sopenharmony_ci		DE_NULL, /* out_clamped */
153e5c31af7Sopenharmony_ci		&irrelevant_tess_level2_rounded_clamped);
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci	irrelevant_tess_level1 = (int)irrelevant_tess_level1_rounded_clamped;
156e5c31af7Sopenharmony_ci	irrelevant_tess_level2 = (int)irrelevant_tess_level2_rounded_clamped;
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_ci	DE_ASSERT(de::abs(irrelevant_tess_level1 - irrelevant_tess_level2) > 0);
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ci	/* Iterate through all test runs for equal spacing */
161e5c31af7Sopenharmony_ci	for (_test_results_iterator test_result_iterator = test_result_iterator_start;
162e5c31af7Sopenharmony_ci		 test_result_iterator != test_result_iterator_end; test_result_iterator++)
163e5c31af7Sopenharmony_ci	{
164e5c31af7Sopenharmony_ci		_test_result test_result = *test_result_iterator;
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ci		if (test_result.irrelevant_tess_level == irrelevant_tess_level1)
167e5c31af7Sopenharmony_ci		{
168e5c31af7Sopenharmony_ci			_test_result test_result_reference =
169e5c31af7Sopenharmony_ci				findTestResult(irrelevant_tess_level2, test_result.outer1_tess_level, test_result.outer2_tess_level,
170e5c31af7Sopenharmony_ci							   TESSELLATION_SHADER_VERTEX_SPACING_EQUAL);
171e5c31af7Sopenharmony_ci
172e5c31af7Sopenharmony_ci			/* data for current test run and the reference one should match */
173e5c31af7Sopenharmony_ci			DE_ASSERT(test_result.n_vertices == test_result_reference.n_vertices);
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ci			for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices; ++n_vertex)
176e5c31af7Sopenharmony_ci			{
177e5c31af7Sopenharmony_ci				const float* vertex_data_1 = (&test_result.rendered_data[0]) + n_vertex * 3;		   /* components */
178e5c31af7Sopenharmony_ci				const float* vertex_data_2 = (&test_result_reference.rendered_data[0]) + n_vertex * 3; /* components */
179e5c31af7Sopenharmony_ci
180e5c31af7Sopenharmony_ci				if (de::abs(vertex_data_1[0] - vertex_data_2[0]) > epsilon ||
181e5c31af7Sopenharmony_ci					de::abs(vertex_data_1[1] - vertex_data_2[1]) > epsilon ||
182e5c31af7Sopenharmony_ci					de::abs(vertex_data_1[2] - vertex_data_2[2]) > epsilon)
183e5c31af7Sopenharmony_ci				{
184e5c31af7Sopenharmony_ci					tcu::TestContext& test = test_result_iterator->parent->parent->getTestContext();
185e5c31af7Sopenharmony_ci
186e5c31af7Sopenharmony_ci					test.getLog()
187e5c31af7Sopenharmony_ci						<< tcu::TestLog::Message
188e5c31af7Sopenharmony_ci						<< "Tessellator generated non-matching data for different tessellation level configurations, "
189e5c31af7Sopenharmony_ci						   "where only irrelevant tessellation levels have been changed; "
190e5c31af7Sopenharmony_ci						<< " data generated for {inner:"
191e5c31af7Sopenharmony_ci						<< " (" << test_result.parent->inner_tess_levels[0] << ", "
192e5c31af7Sopenharmony_ci						<< test_result.parent->inner_tess_levels[1] << ")"
193e5c31af7Sopenharmony_ci						<< " outer:"
194e5c31af7Sopenharmony_ci						<< " (" << test_result.parent->outer_tess_levels[0] << ", "
195e5c31af7Sopenharmony_ci						<< test_result.parent->outer_tess_levels[1] << ", " << test_result.parent->outer_tess_levels[2]
196e5c31af7Sopenharmony_ci						<< ", " << test_result.parent->outer_tess_levels[3] << ")"
197e5c31af7Sopenharmony_ci						<< "}:"
198e5c31af7Sopenharmony_ci						<< " (" << vertex_data_1[0] << ", " << vertex_data_1[1] << ", " << vertex_data_1[2] << ")"
199e5c31af7Sopenharmony_ci						<< ", data generated for {inner:"
200e5c31af7Sopenharmony_ci						<< " (" << test_result_reference.parent->inner_tess_levels[0] << ", "
201e5c31af7Sopenharmony_ci						<< test_result_reference.parent->inner_tess_levels[1] << ")"
202e5c31af7Sopenharmony_ci						<< " outer:"
203e5c31af7Sopenharmony_ci						<< " (" << test_result_reference.parent->outer_tess_levels[0] << ", "
204e5c31af7Sopenharmony_ci						<< test_result_reference.parent->outer_tess_levels[1] << ", "
205e5c31af7Sopenharmony_ci						<< test_result_reference.parent->outer_tess_levels[2] << ", "
206e5c31af7Sopenharmony_ci						<< test_result_reference.parent->outer_tess_levels[3] << ")"
207e5c31af7Sopenharmony_ci						<< "}:"
208e5c31af7Sopenharmony_ci						<< " (" << vertex_data_2[0] << ", " << vertex_data_2[1] << ", " << vertex_data_2[2] << ")"
209e5c31af7Sopenharmony_ci						<< tcu::TestLog::EndMessage;
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci					TCU_FAIL("Invalid amount of unique line segments generated by tessellator");
212e5c31af7Sopenharmony_ci				} /* if (equal and fractional_even data mismatch) */
213e5c31af7Sopenharmony_ci			}	 /* for (all vertices) */
214e5c31af7Sopenharmony_ci		}		  /* if (current test result's irrelelvant tessellation levels match what we're after) */
215e5c31af7Sopenharmony_ci	}			  /* for (all test runs) */
216e5c31af7Sopenharmony_ci}
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci/** Checks that the amount of line segments generated per isoline is as defined by
219e5c31af7Sopenharmony_ci *  second outer tessellation level.
220e5c31af7Sopenharmony_ci *
221e5c31af7Sopenharmony_ci *  This check needs not to operate over all test results generated for a particular
222e5c31af7Sopenharmony_ci *  vertex spacing mode.
223e5c31af7Sopenharmony_ci *
224e5c31af7Sopenharmony_ci *  This function throws a TestError exception if the check fails.
225e5c31af7Sopenharmony_ci *
226e5c31af7Sopenharmony_ci *  @param test_result Test result descriptor to perform the check on.
227e5c31af7Sopenharmony_ci *
228e5c31af7Sopenharmony_ci **/
229e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkSecondOuterTessellationLevelEffect(_test_result&		test_result,
230e5c31af7Sopenharmony_ci																		  const glw::GLenum glMaxTessGenLevelToken)
231e5c31af7Sopenharmony_ci{
232e5c31af7Sopenharmony_ci	typedef float _line_segment_x;
233e5c31af7Sopenharmony_ci	typedef std::pair<_line_segment_x, _line_segment_x> _line_segment;
234e5c31af7Sopenharmony_ci	typedef std::vector<_line_segment> _line_segments;
235e5c31af7Sopenharmony_ci	typedef _line_segments::iterator   _line_segments_iterator;
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci	glcts::Context&		  context = test_result.parent->parent->getContext();
238e5c31af7Sopenharmony_ci	const float			  epsilon = 1e-5f;
239e5c31af7Sopenharmony_ci	_line_segments		  found_line_segments;
240e5c31af7Sopenharmony_ci	const glw::Functions& gl								   = context.getRenderContext().getFunctions();
241e5c31af7Sopenharmony_ci	glw::GLint			  gl_max_tess_gen_level_value		   = 0;
242e5c31af7Sopenharmony_ci	float				  outer_tess_levels1_clamped_rounded   = 0.0f;
243e5c31af7Sopenharmony_ci	unsigned int		  n_line_segments_per_isoline_expected = 0;
244e5c31af7Sopenharmony_ci	unsigned int		  n_unique_line_segments_found		   = 0;
245e5c31af7Sopenharmony_ci
246e5c31af7Sopenharmony_ci	if (test_result.n_vertices != 0)
247e5c31af7Sopenharmony_ci	{
248e5c31af7Sopenharmony_ci		/* Calculate how many isolines we're expecting */
249e5c31af7Sopenharmony_ci		gl.getIntegerv(glMaxTessGenLevelToken, &gl_max_tess_gen_level_value);
250e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci		TessellationShaderUtils::getTessellationLevelAfterVertexSpacing(
253e5c31af7Sopenharmony_ci			test_result.parent->vertex_spacing_mode, test_result.parent->outer_tess_levels[1],
254e5c31af7Sopenharmony_ci			gl_max_tess_gen_level_value, DE_NULL, /* out_clamped */
255e5c31af7Sopenharmony_ci			&outer_tess_levels1_clamped_rounded);
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci		n_line_segments_per_isoline_expected = (unsigned int)outer_tess_levels1_clamped_rounded;
258e5c31af7Sopenharmony_ci
259e5c31af7Sopenharmony_ci		/* Count unique line segments found in all the line segments making up the result data set.  */
260e5c31af7Sopenharmony_ci		for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices;
261e5c31af7Sopenharmony_ci			 n_vertex += 2 /* vertices per line segment */)
262e5c31af7Sopenharmony_ci		{
263e5c31af7Sopenharmony_ci			bool		 was_line_segment_found = false;
264e5c31af7Sopenharmony_ci			const float* vertex1				= (&test_result.rendered_data[0]) + n_vertex * 3; /* components */
265e5c31af7Sopenharmony_ci			float		 vertex1_x				= vertex1[0];
266e5c31af7Sopenharmony_ci			const float* vertex2				= (&test_result.rendered_data[0]) + (n_vertex + 1) * 3; /* components */
267e5c31af7Sopenharmony_ci			float		 vertex2_x				= vertex2[0];
268e5c31af7Sopenharmony_ci
269e5c31af7Sopenharmony_ci			for (_line_segments_iterator found_line_segments_iterator = found_line_segments.begin();
270e5c31af7Sopenharmony_ci				 found_line_segments_iterator != found_line_segments.end(); found_line_segments_iterator++)
271e5c31af7Sopenharmony_ci			{
272e5c31af7Sopenharmony_ci				float& found_vertex1_x = found_line_segments_iterator->first;
273e5c31af7Sopenharmony_ci				float& found_vertex2_x = found_line_segments_iterator->second;
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_ci				if (de::abs(found_vertex1_x - vertex1_x) < epsilon && de::abs(found_vertex2_x - vertex2_x) < epsilon)
276e5c31af7Sopenharmony_ci				{
277e5c31af7Sopenharmony_ci					was_line_segment_found = true;
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci					break;
280e5c31af7Sopenharmony_ci				}
281e5c31af7Sopenharmony_ci			} /* for (all found Ys) */
282e5c31af7Sopenharmony_ci
283e5c31af7Sopenharmony_ci			if (!was_line_segment_found)
284e5c31af7Sopenharmony_ci			{
285e5c31af7Sopenharmony_ci				found_line_segments.push_back(_line_segment(vertex1_x, vertex2_x));
286e5c31af7Sopenharmony_ci			}
287e5c31af7Sopenharmony_ci		} /* for (all vertices) */
288e5c31af7Sopenharmony_ci
289e5c31af7Sopenharmony_ci		/* Compare the values */
290e5c31af7Sopenharmony_ci		n_unique_line_segments_found = (unsigned int)found_line_segments.size();
291e5c31af7Sopenharmony_ci
292e5c31af7Sopenharmony_ci		if (n_unique_line_segments_found != n_line_segments_per_isoline_expected)
293e5c31af7Sopenharmony_ci		{
294e5c31af7Sopenharmony_ci			tcu::TestContext& test = test_result.parent->parent->getTestContext();
295e5c31af7Sopenharmony_ci
296e5c31af7Sopenharmony_ci			test.getLog() << tcu::TestLog::Message << "Tessellator generated an invalid amount of unique line segments:"
297e5c31af7Sopenharmony_ci						  << n_unique_line_segments_found
298e5c31af7Sopenharmony_ci						  << " instead of the expected amount:" << n_line_segments_per_isoline_expected
299e5c31af7Sopenharmony_ci						  << " for the following inner tessellation level configuration:"
300e5c31af7Sopenharmony_ci						  << " (" << test_result.parent->inner_tess_levels[0] << ", "
301e5c31af7Sopenharmony_ci						  << test_result.parent->inner_tess_levels[1] << ")"
302e5c31af7Sopenharmony_ci						  << " and the following outer tesellation level configuration:"
303e5c31af7Sopenharmony_ci						  << " (" << test_result.parent->outer_tess_levels[0] << ", "
304e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[1] << ", "
305e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[2] << ", "
306e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[3] << ")"
307e5c31af7Sopenharmony_ci						  << " and the following vertex spacing mode: " << test_result.parent->vertex_spacing_mode
308e5c31af7Sopenharmony_ci						  << tcu::TestLog::EndMessage;
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid amount of unique line segments generated by tessellator");
311e5c31af7Sopenharmony_ci		}
312e5c31af7Sopenharmony_ci	} /* if (test_run.n_vertices != 0) */
313e5c31af7Sopenharmony_ci}
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci/** Verifies that no vertex making up any of the line segments outputted by the
316e5c31af7Sopenharmony_ci *  tessellator is located at height equal to -1.
317e5c31af7Sopenharmony_ci *
318e5c31af7Sopenharmony_ci *  This check needs not to operate over all test results generated for a particular
319e5c31af7Sopenharmony_ci *  vertex spacing mode.
320e5c31af7Sopenharmony_ci *
321e5c31af7Sopenharmony_ci *  This function throws a TestError exception if the check fails.
322e5c31af7Sopenharmony_ci *
323e5c31af7Sopenharmony_ci *  @param test_result Test result descriptor to perform the check on.
324e5c31af7Sopenharmony_ci *
325e5c31af7Sopenharmony_ci **/
326e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkNoLineSegmentIsDefinedAtHeightOne(_test_result& test_result, glw::GLenum unused)
327e5c31af7Sopenharmony_ci{
328e5c31af7Sopenharmony_ci	(void)unused; // suppress warning
329e5c31af7Sopenharmony_ci
330e5c31af7Sopenharmony_ci	const float epsilon = 1e-5f;
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices; ++n_vertex)
333e5c31af7Sopenharmony_ci	{
334e5c31af7Sopenharmony_ci		const float* vertex = (&test_result.rendered_data[0]) + n_vertex * 3; /* components */
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci		if (de::abs(vertex[1] - 1.0f) < epsilon)
337e5c31af7Sopenharmony_ci		{
338e5c31af7Sopenharmony_ci			tcu::TestContext& test = test_result.parent->parent->getTestContext();
339e5c31af7Sopenharmony_ci
340e5c31af7Sopenharmony_ci			test.getLog() << tcu::TestLog::Message << "Tessellator generated the following coordinate:"
341e5c31af7Sopenharmony_ci						  << " (" << vertex[0] << ", " << vertex[1] << ", " << vertex[2] << ")"
342e5c31af7Sopenharmony_ci						  << " for the following inner tessellation level configuration:"
343e5c31af7Sopenharmony_ci						  << " (" << test_result.parent->inner_tess_levels[0] << ", "
344e5c31af7Sopenharmony_ci						  << test_result.parent->inner_tess_levels[1] << ")"
345e5c31af7Sopenharmony_ci						  << " and the following outer tesellation level configuration:"
346e5c31af7Sopenharmony_ci						  << " (" << test_result.parent->outer_tess_levels[0] << ", "
347e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[1] << ", "
348e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[2] << ", "
349e5c31af7Sopenharmony_ci						  << test_result.parent->outer_tess_levels[3] << ")"
350e5c31af7Sopenharmony_ci						  << " which is invalid: Y must never be equal to 1." << tcu::TestLog::EndMessage;
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid line segment generated by tessellator");
353e5c31af7Sopenharmony_ci		} /* If the Y coordinate is set at 1 */
354e5c31af7Sopenharmony_ci	}	 /* for (all vertices) */
355e5c31af7Sopenharmony_ci}
356e5c31af7Sopenharmony_ci
357e5c31af7Sopenharmony_ci/** Verifies that amount of isolines generated for the same inner+outer level
358e5c31af7Sopenharmony_ci *  configurations but for different vertex spacing modes is exactly the same.
359e5c31af7Sopenharmony_ci *
360e5c31af7Sopenharmony_ci *  This check needs to operate over all test results generated for a particular
361e5c31af7Sopenharmony_ci *  vertex spacing mode.
362e5c31af7Sopenharmony_ci *
363e5c31af7Sopenharmony_ci *  This function throws a TestError exception if the check fails.
364e5c31af7Sopenharmony_ci *
365e5c31af7Sopenharmony_ci **/
366e5c31af7Sopenharmony_civoid TessellationShadersIsolines::checkVertexSpacingDoesNotAffectAmountOfGeneratedIsolines()
367e5c31af7Sopenharmony_ci{
368e5c31af7Sopenharmony_ci	DE_ASSERT(m_tests.find(TESSELLATION_SHADER_VERTEX_SPACING_EQUAL) != m_tests.end());
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ci	_test_results_iterator test_result_iterator_start =
371e5c31af7Sopenharmony_ci		m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].begin();
372e5c31af7Sopenharmony_ci	_test_results_iterator test_result_iterator_end = m_test_results[TESSELLATION_SHADER_VERTEX_SPACING_EQUAL].end();
373e5c31af7Sopenharmony_ci
374e5c31af7Sopenharmony_ci	for (_test_results_iterator test_result_iterator = test_result_iterator_start;
375e5c31af7Sopenharmony_ci		 test_result_iterator != test_result_iterator_end; test_result_iterator++)
376e5c31af7Sopenharmony_ci	{
377e5c31af7Sopenharmony_ci		_test_result& test_result_equal = *test_result_iterator;
378e5c31af7Sopenharmony_ci		_test_result  test_result_fe;
379e5c31af7Sopenharmony_ci		_test_result  test_result_fo;
380e5c31af7Sopenharmony_ci
381e5c31af7Sopenharmony_ci		/* Find a corresponding fractional_even test run descriptor */
382e5c31af7Sopenharmony_ci		test_result_fe =
383e5c31af7Sopenharmony_ci			findTestResult(test_result_equal.irrelevant_tess_level, test_result_equal.outer1_tess_level,
384e5c31af7Sopenharmony_ci						   test_result_equal.outer2_tess_level, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN);
385e5c31af7Sopenharmony_ci		test_result_fo =
386e5c31af7Sopenharmony_ci			findTestResult(test_result_equal.irrelevant_tess_level, test_result_equal.outer1_tess_level,
387e5c31af7Sopenharmony_ci						   test_result_equal.outer2_tess_level, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD);
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci		/* Make sure the amounts match */
390e5c31af7Sopenharmony_ci		if (test_result_equal.n_isolines != test_result_fe.n_isolines ||
391e5c31af7Sopenharmony_ci			test_result_fe.n_isolines != test_result_fo.n_isolines)
392e5c31af7Sopenharmony_ci		{
393e5c31af7Sopenharmony_ci			tcu::TestContext& test = test_result_iterator->parent->parent->getTestContext();
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci			test.getLog() << tcu::TestLog::Message << "Tessellator generated different amount of isolines for EQUAL/"
396e5c31af7Sopenharmony_ci													  "FRACTIONAL_EVEN/FRACTIONAL_ODD vertex spacing modes which is "
397e5c31af7Sopenharmony_ci													  "invalid."
398e5c31af7Sopenharmony_ci						  << tcu::TestLog::EndMessage;
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid amount of unique isolines generated by tessellator");
401e5c31af7Sopenharmony_ci		} /* if (amount of generated isolines does not match) */
402e5c31af7Sopenharmony_ci	}	 /* for (all test runs) */
403e5c31af7Sopenharmony_ci}
404e5c31af7Sopenharmony_ci
405e5c31af7Sopenharmony_ci/** Counts amount of unique isolines in the captured data set and updates
406e5c31af7Sopenharmony_ci *  n_isolines field of user-provided @param test_result instance.
407e5c31af7Sopenharmony_ci *
408e5c31af7Sopenharmony_ci *  @param test_result Test result instance to update.
409e5c31af7Sopenharmony_ci */
410e5c31af7Sopenharmony_civoid TessellationShadersIsolines::countIsolines(_test_result& test_result)
411e5c31af7Sopenharmony_ci{
412e5c31af7Sopenharmony_ci	const float		   epsilon = 1e-5f;
413e5c31af7Sopenharmony_ci	std::vector<float> found_ys;
414e5c31af7Sopenharmony_ci
415e5c31af7Sopenharmony_ci	for (unsigned int n_vertex = 0; n_vertex < test_result.n_vertices; ++n_vertex)
416e5c31af7Sopenharmony_ci	{
417e5c31af7Sopenharmony_ci		bool		 was_y_found = false;
418e5c31af7Sopenharmony_ci		const float* vertex		 = (&test_result.rendered_data[0]) + n_vertex * 3; /* components */
419e5c31af7Sopenharmony_ci		float		 vertex_y	= vertex[1];
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci		for (std::vector<float>::iterator found_ys_iterator = found_ys.begin(); found_ys_iterator != found_ys.end();
422e5c31af7Sopenharmony_ci			 found_ys_iterator++)
423e5c31af7Sopenharmony_ci		{
424e5c31af7Sopenharmony_ci			float& found_y = *found_ys_iterator;
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci			if (de::abs(vertex_y - found_y) < epsilon)
427e5c31af7Sopenharmony_ci			{
428e5c31af7Sopenharmony_ci				was_y_found = true;
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_ci				break;
431e5c31af7Sopenharmony_ci			}
432e5c31af7Sopenharmony_ci		} /* for (all found Ys) */
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci		if (!was_y_found)
435e5c31af7Sopenharmony_ci		{
436e5c31af7Sopenharmony_ci			found_ys.push_back(vertex_y);
437e5c31af7Sopenharmony_ci		}
438e5c31af7Sopenharmony_ci	} /* for (all vertices) */
439e5c31af7Sopenharmony_ci
440e5c31af7Sopenharmony_ci	/* Store the value */
441e5c31af7Sopenharmony_ci	test_result.n_isolines = (unsigned int)found_ys.size();
442e5c31af7Sopenharmony_ci}
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci/** Deinitializes ES objects created for the test. */
445e5c31af7Sopenharmony_civoid TessellationShadersIsolines::deinit()
446e5c31af7Sopenharmony_ci{
447e5c31af7Sopenharmony_ci	/* Call base class' deinit() */
448e5c31af7Sopenharmony_ci	TestCaseBase::deinit();
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_ci	if (!m_is_tessellation_shader_supported)
451e5c31af7Sopenharmony_ci	{
452e5c31af7Sopenharmony_ci		return;
453e5c31af7Sopenharmony_ci	}
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci	/* Reset GL_PATCH_VERTICES_EXT to default value */
458e5c31af7Sopenharmony_ci	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ci	/* Disable GL_RASTERIZER_DISCARD mode */
461e5c31af7Sopenharmony_ci	gl.disable(GL_RASTERIZER_DISCARD);
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	/* Unbind vertex array object */
464e5c31af7Sopenharmony_ci	gl.bindVertexArray(0);
465e5c31af7Sopenharmony_ci
466e5c31af7Sopenharmony_ci	/* Release Utilities instance */
467e5c31af7Sopenharmony_ci	if (m_utils_ptr != NULL)
468e5c31af7Sopenharmony_ci	{
469e5c31af7Sopenharmony_ci		delete m_utils_ptr;
470e5c31af7Sopenharmony_ci
471e5c31af7Sopenharmony_ci		m_utils_ptr = DE_NULL;
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci
474e5c31af7Sopenharmony_ci	if (m_vao_id != 0)
475e5c31af7Sopenharmony_ci	{
476e5c31af7Sopenharmony_ci		gl.deleteVertexArrays(1, &m_vao_id);
477e5c31af7Sopenharmony_ci
478e5c31af7Sopenharmony_ci		m_vao_id = 0;
479e5c31af7Sopenharmony_ci	}
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_ci	/* Free the data structures we allocated for the test */
482e5c31af7Sopenharmony_ci	m_tests.clear();
483e5c31af7Sopenharmony_ci}
484e5c31af7Sopenharmony_ci
485e5c31af7Sopenharmony_ci/** Retrieves test result structure for a particular set of properties.
486e5c31af7Sopenharmony_ci *
487e5c31af7Sopenharmony_ci *  @param irrelevant_tess_level Irrelevant tessellation level the test result descriptor should be using.
488e5c31af7Sopenharmony_ci *  @param outer1_tess_level     First outer tessellation level value  the test result descriptor should be using.
489e5c31af7Sopenharmony_ci *  @param outer2_tess_level     Second outer tessellation level value the test result descriptor should be using.
490e5c31af7Sopenharmony_ci *  @param vertex_spacing_mode   Vertex spacing mode the test result descriptor should be using.
491e5c31af7Sopenharmony_ci *
492e5c31af7Sopenharmony_ci *  This function throws a TestError exception if the test result descriptor the caller is after is not found.
493e5c31af7Sopenharmony_ci *
494e5c31af7Sopenharmony_ci *  @return Test result descriptor of interest.
495e5c31af7Sopenharmony_ci **/
496e5c31af7Sopenharmony_ciTessellationShadersIsolines::_test_result TessellationShadersIsolines::findTestResult(
497e5c31af7Sopenharmony_ci	_irrelevant_tess_level irrelevant_tess_level, _outer1_tess_level outer1_tess_level,
498e5c31af7Sopenharmony_ci	_outer2_tess_level outer2_tess_level, _tessellation_shader_vertex_spacing vertex_spacing_mode)
499e5c31af7Sopenharmony_ci{
500e5c31af7Sopenharmony_ci	DE_ASSERT(m_tests.find(vertex_spacing_mode) != m_tests.end());
501e5c31af7Sopenharmony_ci
502e5c31af7Sopenharmony_ci	_test_results&							  test_results = m_test_results[vertex_spacing_mode];
503e5c31af7Sopenharmony_ci	bool									  has_found	= false;
504e5c31af7Sopenharmony_ci	TessellationShadersIsolines::_test_result result;
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci	for (_test_results_iterator test_results_iterator = test_results.begin();
507e5c31af7Sopenharmony_ci		 test_results_iterator != test_results.end(); test_results_iterator++)
508e5c31af7Sopenharmony_ci	{
509e5c31af7Sopenharmony_ci		if (test_results_iterator->irrelevant_tess_level == irrelevant_tess_level &&
510e5c31af7Sopenharmony_ci			test_results_iterator->outer1_tess_level == outer1_tess_level &&
511e5c31af7Sopenharmony_ci			test_results_iterator->outer2_tess_level == outer2_tess_level)
512e5c31af7Sopenharmony_ci		{
513e5c31af7Sopenharmony_ci			has_found = true;
514e5c31af7Sopenharmony_ci			result	= *test_results_iterator;
515e5c31af7Sopenharmony_ci
516e5c31af7Sopenharmony_ci			break;
517e5c31af7Sopenharmony_ci		}
518e5c31af7Sopenharmony_ci	} /* for (all test runs) */
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_ci	if (!has_found)
521e5c31af7Sopenharmony_ci	{
522e5c31af7Sopenharmony_ci		TCU_FAIL("Requested test run was not found.");
523e5c31af7Sopenharmony_ci	}
524e5c31af7Sopenharmony_ci
525e5c31af7Sopenharmony_ci	return result;
526e5c31af7Sopenharmony_ci}
527e5c31af7Sopenharmony_ci
528e5c31af7Sopenharmony_ci/** Retrieves rendering context associated with the test instance.
529e5c31af7Sopenharmony_ci *
530e5c31af7Sopenharmony_ci *  @return Rendering context.
531e5c31af7Sopenharmony_ci *
532e5c31af7Sopenharmony_ci **/
533e5c31af7Sopenharmony_ciContext& TessellationShadersIsolines::getContext()
534e5c31af7Sopenharmony_ci{
535e5c31af7Sopenharmony_ci	return m_context;
536e5c31af7Sopenharmony_ci}
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ci/** Initializes ES objects necessary to run the test. */
539e5c31af7Sopenharmony_civoid TessellationShadersIsolines::initTest()
540e5c31af7Sopenharmony_ci{
541e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_ci	/* Skip if required extensions are not supported. */
544e5c31af7Sopenharmony_ci	if (!m_is_tessellation_shader_supported)
545e5c31af7Sopenharmony_ci	{
546e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
547e5c31af7Sopenharmony_ci	}
548e5c31af7Sopenharmony_ci
549e5c31af7Sopenharmony_ci	/* Generate Utilities instance */
550e5c31af7Sopenharmony_ci	m_utils_ptr = new TessellationShaderUtils(gl, this);
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	/* Set up vertex array object */
553e5c31af7Sopenharmony_ci	gl.genVertexArrays(1, &m_vao_id);
554e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
555e5c31af7Sopenharmony_ci
556e5c31af7Sopenharmony_ci	gl.bindVertexArray(m_vao_id);
557e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
558e5c31af7Sopenharmony_ci
559e5c31af7Sopenharmony_ci	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value */
560e5c31af7Sopenharmony_ci	glw::GLint gl_max_tess_gen_level_value = 0;
561e5c31af7Sopenharmony_ci
562e5c31af7Sopenharmony_ci	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
563e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname");
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ci	/* Initialize reference tessellation values */
566e5c31af7Sopenharmony_ci	const glw::GLfloat tess_levels[] = { -1.0f, 4.0f, float(gl_max_tess_gen_level_value) * 0.5f,
567e5c31af7Sopenharmony_ci										 float(gl_max_tess_gen_level_value) };
568e5c31af7Sopenharmony_ci	const unsigned int n_tess_levels = sizeof(tess_levels) / sizeof(tess_levels[0]);
569e5c31af7Sopenharmony_ci
570e5c31af7Sopenharmony_ci	m_irrelevant_tess_value_1 = tess_levels[0];
571e5c31af7Sopenharmony_ci	m_irrelevant_tess_value_2 = tess_levels[1];
572e5c31af7Sopenharmony_ci
573e5c31af7Sopenharmony_ci	/* Initialize all test passes.
574e5c31af7Sopenharmony_ci	 *
575e5c31af7Sopenharmony_ci	 * Make sure each relevant outer tessellation level iterates through values
576e5c31af7Sopenharmony_ci	 * of our interest
577e5c31af7Sopenharmony_ci	 */
578e5c31af7Sopenharmony_ci	for (unsigned int outer1_tess_level_index = 0; outer1_tess_level_index < n_tess_levels; ++outer1_tess_level_index)
579e5c31af7Sopenharmony_ci	{
580e5c31af7Sopenharmony_ci		for (unsigned int outer2_tess_level_index = 0; outer2_tess_level_index < n_tess_levels;
581e5c31af7Sopenharmony_ci			 ++outer2_tess_level_index)
582e5c31af7Sopenharmony_ci		{
583e5c31af7Sopenharmony_ci			/* To make the test execute in a reasonable time frame, just use
584e5c31af7Sopenharmony_ci			 * two different levels for the outer tessellation levels */
585e5c31af7Sopenharmony_ci			DE_STATIC_ASSERT(n_tess_levels >= 2);
586e5c31af7Sopenharmony_ci
587e5c31af7Sopenharmony_ci			for (unsigned int other_tess_level_index = 0; other_tess_level_index < 2 /* see comment */;
588e5c31af7Sopenharmony_ci				 ++other_tess_level_index)
589e5c31af7Sopenharmony_ci			{
590e5c31af7Sopenharmony_ci				float inner_tess_levels[2] = { tess_levels[other_tess_level_index],
591e5c31af7Sopenharmony_ci											   tess_levels[other_tess_level_index] };
592e5c31af7Sopenharmony_ci				float outer_tess_levels[4] = { tess_levels[outer1_tess_level_index],
593e5c31af7Sopenharmony_ci											   tess_levels[outer2_tess_level_index],
594e5c31af7Sopenharmony_ci											   tess_levels[other_tess_level_index],
595e5c31af7Sopenharmony_ci											   tess_levels[other_tess_level_index] };
596e5c31af7Sopenharmony_ci
597e5c31af7Sopenharmony_ci				/* Finally, iterate over three vertex spacing modes */
598e5c31af7Sopenharmony_ci				_tessellation_shader_vertex_spacing vertex_spacing_mode;
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_ci				const _tessellation_shader_vertex_spacing vs_modes[] = {
601e5c31af7Sopenharmony_ci					TESSELLATION_SHADER_VERTEX_SPACING_EQUAL, TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_EVEN,
602e5c31af7Sopenharmony_ci					TESSELLATION_SHADER_VERTEX_SPACING_FRACTIONAL_ODD
603e5c31af7Sopenharmony_ci				};
604e5c31af7Sopenharmony_ci				const int n_vs_modes = sizeof(vs_modes) / sizeof(vs_modes[0]);
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ci				for (int n_vs_mode = 0; n_vs_mode < n_vs_modes; ++n_vs_mode)
607e5c31af7Sopenharmony_ci				{
608e5c31af7Sopenharmony_ci					vertex_spacing_mode = vs_modes[n_vs_mode];
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ci					_test_descriptor test;
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ci					initTestDescriptor(vertex_spacing_mode, inner_tess_levels, outer_tess_levels,
613e5c31af7Sopenharmony_ci									   tess_levels[other_tess_level_index], test);
614e5c31af7Sopenharmony_ci
615e5c31af7Sopenharmony_ci					m_tests[vertex_spacing_mode].push_back(test);
616e5c31af7Sopenharmony_ci				} /* for (all available vertex spacing modes) */
617e5c31af7Sopenharmony_ci			}	 /* for (all irrelevant tessellation levels) */
618e5c31af7Sopenharmony_ci		}		  /* for (all defined second outer tessellation levels) */
619e5c31af7Sopenharmony_ci	}			  /* for (all defined first outer tessellation levels) */
620e5c31af7Sopenharmony_ci}
621e5c31af7Sopenharmony_ci
622e5c31af7Sopenharmony_ci/** Initializes all ES objects necessary to run a specific test pass.
623e5c31af7Sopenharmony_ci *
624e5c31af7Sopenharmony_ci *  @param vertex_spacing        Vertex spacing mode to initialize the test descriptor with.
625e5c31af7Sopenharmony_ci *  @param inner_tess_levels     Two FP values defining subsequent inner tessellation levels
626e5c31af7Sopenharmony_ci *                               to be used for initializing the test descriptor. Must NOT be
627e5c31af7Sopenharmony_ci *                               NULL.
628e5c31af7Sopenharmony_ci *  @param outer_tess_levels     Four FP values defining subsequent outer tessellation levels
629e5c31af7Sopenharmony_ci *                               to be used for initializing the test descriptor. Must NOT be
630e5c31af7Sopenharmony_ci *                               NULL.
631e5c31af7Sopenharmony_ci *  @param irrelevant_tess_level Value to be used to set irrelevant tessellation level values.
632e5c31af7Sopenharmony_ci *  @param test                  Test descriptor to fill with IDs of initialized objects.
633e5c31af7Sopenharmony_ci **/
634e5c31af7Sopenharmony_civoid TessellationShadersIsolines::initTestDescriptor(_tessellation_shader_vertex_spacing vertex_spacing,
635e5c31af7Sopenharmony_ci													 const float* inner_tess_levels, const float* outer_tess_levels,
636e5c31af7Sopenharmony_ci													 float irrelevant_tess_level, _test_descriptor& test)
637e5c31af7Sopenharmony_ci{
638e5c31af7Sopenharmony_ci	memcpy(test.inner_tess_levels, inner_tess_levels, sizeof(test.inner_tess_levels));
639e5c31af7Sopenharmony_ci	memcpy(test.outer_tess_levels, outer_tess_levels, sizeof(test.outer_tess_levels));
640e5c31af7Sopenharmony_ci
641e5c31af7Sopenharmony_ci	test.parent				   = this;
642e5c31af7Sopenharmony_ci	test.irrelevant_tess_level = irrelevant_tess_level;
643e5c31af7Sopenharmony_ci	test.vertex_spacing_mode   = vertex_spacing;
644e5c31af7Sopenharmony_ci}
645e5c31af7Sopenharmony_ci
646e5c31af7Sopenharmony_ci/** Executes the test.
647e5c31af7Sopenharmony_ci *
648e5c31af7Sopenharmony_ci *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
649e5c31af7Sopenharmony_ci *
650e5c31af7Sopenharmony_ci *  Note the function throws exception should an error occur!
651e5c31af7Sopenharmony_ci *
652e5c31af7Sopenharmony_ci *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
653e5c31af7Sopenharmony_ci **/
654e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShadersIsolines::iterate(void)
655e5c31af7Sopenharmony_ci{
656e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
657e5c31af7Sopenharmony_ci
658e5c31af7Sopenharmony_ci	initTest();
659e5c31af7Sopenharmony_ci
660e5c31af7Sopenharmony_ci	/* We only need to use one vertex per so go for it */
661e5c31af7Sopenharmony_ci	gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 1);
662e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname");
663e5c31af7Sopenharmony_ci
664e5c31af7Sopenharmony_ci	/* We don't need to rasterize anything in this test */
665e5c31af7Sopenharmony_ci	gl.enable(GL_RASTERIZER_DISCARD);
666e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) failed");
667e5c31af7Sopenharmony_ci
668e5c31af7Sopenharmony_ci	/* Retrieve GL_MAX_TESS_GEN_LEVEL_EXT value before we continue */
669e5c31af7Sopenharmony_ci	glw::GLint gl_max_tess_gen_level_value = 0;
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_ci	gl.getIntegerv(m_glExtTokens.MAX_TESS_GEN_LEVEL, &gl_max_tess_gen_level_value);
672e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_TESS_GEN_LEVEL_EXT pname.");
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci	/* To perform actual tests, we need to first retrieve the tessellated coordinates data.
675e5c31af7Sopenharmony_ci	 * Run all tests configured and fill per-test buffer with the information.
676e5c31af7Sopenharmony_ci	 **/
677e5c31af7Sopenharmony_ci	for (_tests_per_vertex_spacing_map_iterator vs_key_iterator = m_tests.begin(); vs_key_iterator != m_tests.end();
678e5c31af7Sopenharmony_ci		 vs_key_iterator++)
679e5c31af7Sopenharmony_ci	{
680e5c31af7Sopenharmony_ci		for (_tests_const_iterator test_iterator = vs_key_iterator->second.begin();
681e5c31af7Sopenharmony_ci			 test_iterator != vs_key_iterator->second.end(); test_iterator++)
682e5c31af7Sopenharmony_ci		{
683e5c31af7Sopenharmony_ci			const _test_descriptor& test = *test_iterator;
684e5c31af7Sopenharmony_ci
685e5c31af7Sopenharmony_ci			/* Capture tessellation data for considered configuration */
686e5c31af7Sopenharmony_ci			unsigned int n_rendered_vertices = m_utils_ptr->getAmountOfVerticesGeneratedByTessellator(
687e5c31af7Sopenharmony_ci				TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, test.inner_tess_levels, test.outer_tess_levels,
688e5c31af7Sopenharmony_ci				test.vertex_spacing_mode, false); /* is_point_mode_enabled */
689e5c31af7Sopenharmony_ci			std::vector<char> rendered_data = m_utils_ptr->getDataGeneratedByTessellator(
690e5c31af7Sopenharmony_ci				test.inner_tess_levels, false, /* point mode */
691e5c31af7Sopenharmony_ci				TESSELLATION_SHADER_PRIMITIVE_MODE_ISOLINES, TESSELLATION_SHADER_VERTEX_ORDERING_CCW,
692e5c31af7Sopenharmony_ci				test.vertex_spacing_mode, test.outer_tess_levels);
693e5c31af7Sopenharmony_ci
694e5c31af7Sopenharmony_ci			/* Store the data in a test result descriptor */
695e5c31af7Sopenharmony_ci			_test_result result;
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci			result.n_vertices			 = n_rendered_vertices;
698e5c31af7Sopenharmony_ci			result.parent				 = &test;
699e5c31af7Sopenharmony_ci			result.irrelevant_tess_level = (int)test.irrelevant_tess_level;
700e5c31af7Sopenharmony_ci			result.outer1_tess_level	 = (int)test.outer_tess_levels[0];
701e5c31af7Sopenharmony_ci			result.outer2_tess_level	 = (int)test.outer_tess_levels[1];
702e5c31af7Sopenharmony_ci			result.rendered_data.resize(rendered_data.size() / sizeof(float));
703e5c31af7Sopenharmony_ci			if (0 != rendered_data.size())
704e5c31af7Sopenharmony_ci			{
705e5c31af7Sopenharmony_ci				memcpy(&result.rendered_data[0], &rendered_data[0], rendered_data.size());
706e5c31af7Sopenharmony_ci			}
707e5c31af7Sopenharmony_ci			if (result.rendered_data.size() > 0)
708e5c31af7Sopenharmony_ci			{
709e5c31af7Sopenharmony_ci				countIsolines(result);
710e5c31af7Sopenharmony_ci			}
711e5c31af7Sopenharmony_ci
712e5c31af7Sopenharmony_ci			/* Store the test run descriptor. */
713e5c31af7Sopenharmony_ci			m_test_results[test.vertex_spacing_mode].push_back(result);
714e5c31af7Sopenharmony_ci		}
715e5c31af7Sopenharmony_ci	}
716e5c31af7Sopenharmony_ci
717e5c31af7Sopenharmony_ci	/* Now we can proceed with actual tests */
718e5c31af7Sopenharmony_ci	/* (test 1): Make sure amount of isolines is determined by first outer tessellation level */
719e5c31af7Sopenharmony_ci	runForAllTestResults(checkFirstOuterTessellationLevelEffect);
720e5c31af7Sopenharmony_ci
721e5c31af7Sopenharmony_ci	/* (test 2): Make sure amount of line segments per height is determined by second outer
722e5c31af7Sopenharmony_ci	 *           tessellation level.
723e5c31af7Sopenharmony_ci	 */
724e5c31af7Sopenharmony_ci	runForAllTestResults(checkSecondOuterTessellationLevelEffect);
725e5c31af7Sopenharmony_ci
726e5c31af7Sopenharmony_ci	/* (test 3): Make sure 3rd, 4th outer tessellation levels, as well as all inner tessellation
727e5c31af7Sopenharmony_ci	 *           levels have no impact on the tessellated coordinates */
728e5c31af7Sopenharmony_ci	checkIrrelevantTessellationLevelsHaveNoEffect();
729e5c31af7Sopenharmony_ci
730e5c31af7Sopenharmony_ci	/* (test 4): Make sure no matter what vertex spacing is requested in TC stage, it is always
731e5c31af7Sopenharmony_ci	 *           equal_spacing that is applied.
732e5c31af7Sopenharmony_ci	 */
733e5c31af7Sopenharmony_ci	checkVertexSpacingDoesNotAffectAmountOfGeneratedIsolines();
734e5c31af7Sopenharmony_ci
735e5c31af7Sopenharmony_ci	/* (test 5): Make sure that no data set features a line segment at height of 1. */
736e5c31af7Sopenharmony_ci	runForAllTestResults(checkNoLineSegmentIsDefinedAtHeightOne);
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ci	/* All done */
739e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
740e5c31af7Sopenharmony_ci	return STOP;
741e5c31af7Sopenharmony_ci}
742e5c31af7Sopenharmony_ci
743e5c31af7Sopenharmony_ci/** Calls the caller-provided function provided for each test result descriptor
744e5c31af7Sopenharmony_ci *  created during pre-computation stage.
745e5c31af7Sopenharmony_ci *
746e5c31af7Sopenharmony_ci *  @param pProcessTestRun Function pointer to call. The function will be called
747e5c31af7Sopenharmony_ci *                         exactly once for each cached test result descriptor.
748e5c31af7Sopenharmony_ci *
749e5c31af7Sopenharmony_ci **/
750e5c31af7Sopenharmony_civoid TessellationShadersIsolines::runForAllTestResults(PFNTESTRESULTPROCESSORPROC pProcessTestResult)
751e5c31af7Sopenharmony_ci{
752e5c31af7Sopenharmony_ci	for (_test_results_per_vertex_spacing_map_iterator vs_key_iterator = m_test_results.begin();
753e5c31af7Sopenharmony_ci		 vs_key_iterator != m_test_results.end(); vs_key_iterator++)
754e5c31af7Sopenharmony_ci	{
755e5c31af7Sopenharmony_ci		for (_test_results_iterator test_results_iterator = vs_key_iterator->second.begin();
756e5c31af7Sopenharmony_ci			 test_results_iterator != vs_key_iterator->second.end(); test_results_iterator++)
757e5c31af7Sopenharmony_ci		{
758e5c31af7Sopenharmony_ci			_test_result& test_result = *test_results_iterator;
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_ci			pProcessTestResult(test_result, m_glExtTokens.MAX_TESS_GEN_LEVEL);
761e5c31af7Sopenharmony_ci		} /* for (all level3 keys) */
762e5c31af7Sopenharmony_ci	}	 /* for (all vertex spacing modes) */
763e5c31af7Sopenharmony_ci}
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci} /* namespace glcts */
766