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 "esextcTessellationShaderProperties.hpp"
25e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
26e5c31af7Sopenharmony_ci#include "gluDefs.hpp"
27e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
28e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
29e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
30e5c31af7Sopenharmony_ci#include <cmath>
31e5c31af7Sopenharmony_ci#include <cstring>
32e5c31af7Sopenharmony_ci
33e5c31af7Sopenharmony_cinamespace glcts
34e5c31af7Sopenharmony_ci{
35e5c31af7Sopenharmony_ci/** Constructor
36e5c31af7Sopenharmony_ci *
37e5c31af7Sopenharmony_ci * @param context Test context
38e5c31af7Sopenharmony_ci **/
39e5c31af7Sopenharmony_ciTessellationShaderPropertiesDefaultContextWideValues::TessellationShaderPropertiesDefaultContextWideValues(
40e5c31af7Sopenharmony_ci	Context& context, const ExtParameters& extParams)
41e5c31af7Sopenharmony_ci	: TestCaseBase(context, extParams, "default_values_of_context_wide_properties",
42e5c31af7Sopenharmony_ci				   "Verifies default values of context-wide tessellation stage properties")
43e5c31af7Sopenharmony_ci{
44e5c31af7Sopenharmony_ci	/* Left blank on purpose */
45e5c31af7Sopenharmony_ci}
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ci/** Executes the test.
48e5c31af7Sopenharmony_ci *
49e5c31af7Sopenharmony_ci *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
50e5c31af7Sopenharmony_ci *
51e5c31af7Sopenharmony_ci *  Note the function throws exception should an error occur!
52e5c31af7Sopenharmony_ci *
53e5c31af7Sopenharmony_ci *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
54e5c31af7Sopenharmony_ci **/
55e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShaderPropertiesDefaultContextWideValues::iterate(void)
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_ci	/* Do not execute if required extensions are not supported. */
58e5c31af7Sopenharmony_ci	if (!m_is_tessellation_shader_supported)
59e5c31af7Sopenharmony_ci	{
60e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
61e5c31af7Sopenharmony_ci	}
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci	/* Iterate through all context-wide properties and compare expected values
64e5c31af7Sopenharmony_ci	 * against the reference ones
65e5c31af7Sopenharmony_ci	 */
66e5c31af7Sopenharmony_ci	const float			  epsilon = (float)1e-5;
67e5c31af7Sopenharmony_ci	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci	const glw::GLint property_value_data[] = { /* pname */ /* n components */ /* default value */
70e5c31af7Sopenharmony_ci											   static_cast<glw::GLint>(m_glExtTokens.PATCH_VERTICES), 1, 3,
71e5c31af7Sopenharmony_ci											   /* The following values are only applicable to Desktop OpenGL. */
72e5c31af7Sopenharmony_ci											   GL_PATCH_DEFAULT_OUTER_LEVEL, 4, 1, GL_PATCH_DEFAULT_INNER_LEVEL, 2, 1 };
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ci	const unsigned int n_properties = (glu::isContextTypeES(m_context.getRenderContext().getType())) ? 1 : 3;
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ci	for (unsigned int n_property = 0; n_property < n_properties; ++n_property)
77e5c31af7Sopenharmony_ci	{
78e5c31af7Sopenharmony_ci		glw::GLboolean bool_value[4]  = { GL_FALSE };
79e5c31af7Sopenharmony_ci		glw::GLfloat   float_value[4] = { 0.0f };
80e5c31af7Sopenharmony_ci		glw::GLint	 int_value[4]   = { 0 };
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci		glw::GLenum pname		   = property_value_data[n_property * 3 + 0];
83e5c31af7Sopenharmony_ci		glw::GLint  n_components   = property_value_data[n_property * 3 + 1];
84e5c31af7Sopenharmony_ci		glw::GLint  expected_value = property_value_data[n_property * 3 + 2];
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_ci		/* Call all relevant getters */
87e5c31af7Sopenharmony_ci		gl.getBooleanv(pname, bool_value);
88e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() failed.");
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_ci		gl.getFloatv(pname, float_value);
91e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() failed.");
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci		gl.getIntegerv(pname, int_value);
94e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed.");
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ci		/* Compare retrieved vector value components against expected value */
97e5c31af7Sopenharmony_ci		glw::GLboolean expected_bool_value[4] = {
98e5c31af7Sopenharmony_ci			(expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE,
99e5c31af7Sopenharmony_ci			(expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE,
100e5c31af7Sopenharmony_ci			(expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE,
101e5c31af7Sopenharmony_ci			(expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE
102e5c31af7Sopenharmony_ci		};
103e5c31af7Sopenharmony_ci		glw::GLint expected_int_value[4] = { expected_value, expected_value, expected_value, expected_value };
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_ci		if (memcmp(expected_bool_value, bool_value, sizeof(bool) * n_components) != 0)
106e5c31af7Sopenharmony_ci		{
107e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "glGetBooleanv() called for pname " << pname
108e5c31af7Sopenharmony_ci							   << " reported invalid value." << tcu::TestLog::EndMessage;
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported by glGetBooleanv()");
111e5c31af7Sopenharmony_ci		}
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci		if (memcmp(expected_int_value, int_value, sizeof(int) * n_components) != 0)
114e5c31af7Sopenharmony_ci		{
115e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "glGetIntegerv() called for pname " << pname
116e5c31af7Sopenharmony_ci							   << " reported invalid value." << tcu::TestLog::EndMessage;
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported by glGetIntegerv()");
119e5c31af7Sopenharmony_ci		}
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci		if ((n_components >= 1 && de::abs(float_value[0] - (float)expected_value) > epsilon) ||
122e5c31af7Sopenharmony_ci			(n_components >= 2 && de::abs(float_value[1] - (float)expected_value) > epsilon) ||
123e5c31af7Sopenharmony_ci			(n_components >= 3 && de::abs(float_value[2] - (float)expected_value) > epsilon) ||
124e5c31af7Sopenharmony_ci			(n_components >= 4 && de::abs(float_value[3] - (float)expected_value) > epsilon))
125e5c31af7Sopenharmony_ci		{
126e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "glGetFloatv() called for pname " << pname
127e5c31af7Sopenharmony_ci							   << " reported invalid value." << tcu::TestLog::EndMessage;
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported by glGetFloatv()");
130e5c31af7Sopenharmony_ci		}
131e5c31af7Sopenharmony_ci	} /* for (all properties) */
132e5c31af7Sopenharmony_ci
133e5c31af7Sopenharmony_ci	/* All done */
134e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
135e5c31af7Sopenharmony_ci	return STOP;
136e5c31af7Sopenharmony_ci}
137e5c31af7Sopenharmony_ci
138e5c31af7Sopenharmony_ci/** Constructor
139e5c31af7Sopenharmony_ci *
140e5c31af7Sopenharmony_ci * @param context Test context
141e5c31af7Sopenharmony_ci **/
142e5c31af7Sopenharmony_ciTessellationShaderPropertiesProgramObject::TessellationShaderPropertiesProgramObject(Context&			  context,
143e5c31af7Sopenharmony_ci																					 const ExtParameters& extParams)
144e5c31af7Sopenharmony_ci	: TestCaseBase(context, extParams, "program_object_properties",
145e5c31af7Sopenharmony_ci				   "Verifies tessellation-specific properties of program objects are reported correctly.")
146e5c31af7Sopenharmony_ci	, m_fs_id(0)
147e5c31af7Sopenharmony_ci	, m_po_id(0)
148e5c31af7Sopenharmony_ci	, m_tc_id(0)
149e5c31af7Sopenharmony_ci	, m_te_id(0)
150e5c31af7Sopenharmony_ci	, m_vs_id(0)
151e5c31af7Sopenharmony_ci{
152e5c31af7Sopenharmony_ci	/* Left blank on purpose */
153e5c31af7Sopenharmony_ci}
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci/** Deinitializes ES objects created for the test */
156e5c31af7Sopenharmony_civoid TessellationShaderPropertiesProgramObject::deinit(void)
157e5c31af7Sopenharmony_ci{
158e5c31af7Sopenharmony_ci	/* Call base class' deinit() */
159e5c31af7Sopenharmony_ci	TestCaseBase::deinit();
160e5c31af7Sopenharmony_ci
161e5c31af7Sopenharmony_ci	/* Release any ES objects created */
162e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
163e5c31af7Sopenharmony_ci
164e5c31af7Sopenharmony_ci	if (m_fs_id != 0)
165e5c31af7Sopenharmony_ci	{
166e5c31af7Sopenharmony_ci		gl.deleteShader(m_fs_id);
167e5c31af7Sopenharmony_ci
168e5c31af7Sopenharmony_ci		m_fs_id = 0;
169e5c31af7Sopenharmony_ci	}
170e5c31af7Sopenharmony_ci
171e5c31af7Sopenharmony_ci	if (m_po_id != 0)
172e5c31af7Sopenharmony_ci	{
173e5c31af7Sopenharmony_ci		gl.deleteProgram(m_po_id);
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ci		m_po_id = 0;
176e5c31af7Sopenharmony_ci	}
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_ci	if (m_tc_id != 0)
179e5c31af7Sopenharmony_ci	{
180e5c31af7Sopenharmony_ci		gl.deleteShader(m_tc_id);
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci		m_tc_id = 0;
183e5c31af7Sopenharmony_ci	}
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci	if (m_te_id != 0)
186e5c31af7Sopenharmony_ci	{
187e5c31af7Sopenharmony_ci		gl.deleteShader(m_te_id);
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci		m_te_id = 0;
190e5c31af7Sopenharmony_ci	}
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ci	if (m_vs_id != 0)
193e5c31af7Sopenharmony_ci	{
194e5c31af7Sopenharmony_ci		gl.deleteShader(m_vs_id);
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ci		m_vs_id = 0;
197e5c31af7Sopenharmony_ci	}
198e5c31af7Sopenharmony_ci}
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci/** Initializes ES objects necessary to execute the test */
201e5c31af7Sopenharmony_civoid TessellationShaderPropertiesProgramObject::initTest(void)
202e5c31af7Sopenharmony_ci{
203e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci	/* Do not execute if required extension is not supported */
206e5c31af7Sopenharmony_ci	if (!m_is_tessellation_shader_supported)
207e5c31af7Sopenharmony_ci	{
208e5c31af7Sopenharmony_ci		return;
209e5c31af7Sopenharmony_ci	}
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci	/* Generate all objects */
212e5c31af7Sopenharmony_ci	m_po_id = gl.createProgram();
213e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_ci	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
216e5c31af7Sopenharmony_ci	m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
217e5c31af7Sopenharmony_ci	m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
218e5c31af7Sopenharmony_ci	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
219e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci	/* Attach the shader to the program object */
222e5c31af7Sopenharmony_ci	gl.attachShader(m_po_id, m_fs_id);
223e5c31af7Sopenharmony_ci	gl.attachShader(m_po_id, m_tc_id);
224e5c31af7Sopenharmony_ci	gl.attachShader(m_po_id, m_te_id);
225e5c31af7Sopenharmony_ci	gl.attachShader(m_po_id, m_vs_id);
226e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
227e5c31af7Sopenharmony_ci
228e5c31af7Sopenharmony_ci	/* Since this test does not care much about fragment & vertex shaders, set
229e5c31af7Sopenharmony_ci	 * their bodies and compile these shaders now */
230e5c31af7Sopenharmony_ci	const char* fs_body = "${VERSION}\n"
231e5c31af7Sopenharmony_ci						  "\n"
232e5c31af7Sopenharmony_ci						  "void main()\n"
233e5c31af7Sopenharmony_ci						  "{\n"
234e5c31af7Sopenharmony_ci						  "}\n";
235e5c31af7Sopenharmony_ci
236e5c31af7Sopenharmony_ci	const char* vs_body = "${VERSION}\n"
237e5c31af7Sopenharmony_ci						  "\n"
238e5c31af7Sopenharmony_ci						  "void main()\n"
239e5c31af7Sopenharmony_ci						  "{\n"
240e5c31af7Sopenharmony_ci						  "}\n";
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ci	glw::GLint fs_compile_status = GL_FALSE;
243e5c31af7Sopenharmony_ci	glw::GLint vs_compile_status = GL_FALSE;
244e5c31af7Sopenharmony_ci
245e5c31af7Sopenharmony_ci	shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
246e5c31af7Sopenharmony_ci	shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
247e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed");
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_ci	gl.compileShader(m_fs_id);
250e5c31af7Sopenharmony_ci	gl.compileShader(m_vs_id);
251e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	gl.getShaderiv(m_fs_id, GL_COMPILE_STATUS, &fs_compile_status);
254e5c31af7Sopenharmony_ci	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &vs_compile_status);
255e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci	if (fs_compile_status != GL_TRUE)
258e5c31af7Sopenharmony_ci	{
259e5c31af7Sopenharmony_ci		TCU_FAIL("Could not compile fragment shader");
260e5c31af7Sopenharmony_ci	}
261e5c31af7Sopenharmony_ci
262e5c31af7Sopenharmony_ci	if (vs_compile_status != GL_TRUE)
263e5c31af7Sopenharmony_ci	{
264e5c31af7Sopenharmony_ci		TCU_FAIL("Could not compile vertex shader");
265e5c31af7Sopenharmony_ci	}
266e5c31af7Sopenharmony_ci}
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci/** Executes the test.
269e5c31af7Sopenharmony_ci *
270e5c31af7Sopenharmony_ci *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
271e5c31af7Sopenharmony_ci *
272e5c31af7Sopenharmony_ci *  Note the function throws exception should an error occur!
273e5c31af7Sopenharmony_ci *
274e5c31af7Sopenharmony_ci *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
275e5c31af7Sopenharmony_ci **/
276e5c31af7Sopenharmony_citcu::TestNode::IterateResult TessellationShaderPropertiesProgramObject::iterate(void)
277e5c31af7Sopenharmony_ci{
278e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
279e5c31af7Sopenharmony_ci
280e5c31af7Sopenharmony_ci	/* Do not execute if required extensions are not supported. */
281e5c31af7Sopenharmony_ci	if (!m_is_tessellation_shader_supported)
282e5c31af7Sopenharmony_ci	{
283e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
284e5c31af7Sopenharmony_ci	}
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_ci	/* Initialize ES test objects */
287e5c31af7Sopenharmony_ci	initTest();
288e5c31af7Sopenharmony_ci
289e5c31af7Sopenharmony_ci	/* Test 1: Default values. Values as per spec, define as little qualifiers as possible */
290e5c31af7Sopenharmony_ci	_test_descriptor test_1;
291e5c31af7Sopenharmony_ci
292e5c31af7Sopenharmony_ci	test_1.expected_control_output_vertices_value = 4;
293e5c31af7Sopenharmony_ci	test_1.expected_gen_mode_value				  = m_glExtTokens.QUADS;
294e5c31af7Sopenharmony_ci	test_1.expected_gen_point_mode_value		  = GL_FALSE;
295e5c31af7Sopenharmony_ci	test_1.expected_gen_spacing_value			  = GL_EQUAL;
296e5c31af7Sopenharmony_ci	test_1.expected_gen_vertex_order_value		  = GL_CCW;
297e5c31af7Sopenharmony_ci	test_1.tc_body								  = "${VERSION}\n"
298e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
299e5c31af7Sopenharmony_ci					 "\n"
300e5c31af7Sopenharmony_ci					 "layout(vertices=4) out;\n"
301e5c31af7Sopenharmony_ci					 "\n"
302e5c31af7Sopenharmony_ci					 "void main()\n"
303e5c31af7Sopenharmony_ci					 "{\n"
304e5c31af7Sopenharmony_ci					 "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
305e5c31af7Sopenharmony_ci					 "}\n";
306e5c31af7Sopenharmony_ci	test_1.te_body = "${VERSION}\n"
307e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
308e5c31af7Sopenharmony_ci					 "\n"
309e5c31af7Sopenharmony_ci					 "layout(quads) in;\n"
310e5c31af7Sopenharmony_ci					 "\n"
311e5c31af7Sopenharmony_ci					 "void main()\n"
312e5c31af7Sopenharmony_ci					 "{\n"
313e5c31af7Sopenharmony_ci					 "    gl_Position = gl_in[0].gl_Position;\n"
314e5c31af7Sopenharmony_ci					 "}\n";
315e5c31af7Sopenharmony_ci
316e5c31af7Sopenharmony_ci	/* Test 2: 16 vertices per patch + isolines + fractional_even_spacing + cw combination */
317e5c31af7Sopenharmony_ci	_test_descriptor test_2;
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_ci	test_2.expected_control_output_vertices_value = 16;
320e5c31af7Sopenharmony_ci	test_2.expected_gen_mode_value				  = m_glExtTokens.ISOLINES;
321e5c31af7Sopenharmony_ci	test_2.expected_gen_point_mode_value		  = GL_FALSE;
322e5c31af7Sopenharmony_ci	test_2.expected_gen_spacing_value			  = m_glExtTokens.FRACTIONAL_EVEN;
323e5c31af7Sopenharmony_ci	test_2.expected_gen_vertex_order_value		  = GL_CW;
324e5c31af7Sopenharmony_ci	test_2.tc_body								  = "${VERSION}\n"
325e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
326e5c31af7Sopenharmony_ci					 "\n"
327e5c31af7Sopenharmony_ci					 "layout(vertices=16) out;\n"
328e5c31af7Sopenharmony_ci					 "\n"
329e5c31af7Sopenharmony_ci					 "void main()\n"
330e5c31af7Sopenharmony_ci					 "{\n"
331e5c31af7Sopenharmony_ci					 "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
332e5c31af7Sopenharmony_ci					 "}\n";
333e5c31af7Sopenharmony_ci	test_2.te_body = "${VERSION}\n"
334e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
335e5c31af7Sopenharmony_ci					 "\n"
336e5c31af7Sopenharmony_ci					 "layout(isolines, fractional_even_spacing, cw) in;\n"
337e5c31af7Sopenharmony_ci					 "\n"
338e5c31af7Sopenharmony_ci					 "void main()\n"
339e5c31af7Sopenharmony_ci					 "{\n"
340e5c31af7Sopenharmony_ci					 "    gl_Position = gl_in[0].gl_Position;\n"
341e5c31af7Sopenharmony_ci					 "}\n";
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_ci	/* Test 3: 32 vertices per patch + triangles + fractional_odd_spacing + ccw combination + point mode*/
344e5c31af7Sopenharmony_ci	_test_descriptor test_3;
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci	test_3.expected_control_output_vertices_value = 32;
347e5c31af7Sopenharmony_ci	test_3.expected_gen_mode_value				  = GL_TRIANGLES;
348e5c31af7Sopenharmony_ci	test_3.expected_gen_point_mode_value		  = GL_TRUE;
349e5c31af7Sopenharmony_ci	test_3.expected_gen_spacing_value			  = m_glExtTokens.FRACTIONAL_ODD;
350e5c31af7Sopenharmony_ci	test_3.expected_gen_vertex_order_value		  = GL_CCW;
351e5c31af7Sopenharmony_ci	test_3.tc_body								  = "${VERSION}\n"
352e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
353e5c31af7Sopenharmony_ci					 "\n"
354e5c31af7Sopenharmony_ci					 "layout(vertices=32) out;\n"
355e5c31af7Sopenharmony_ci					 "\n"
356e5c31af7Sopenharmony_ci					 "void main()\n"
357e5c31af7Sopenharmony_ci					 "{\n"
358e5c31af7Sopenharmony_ci					 "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
359e5c31af7Sopenharmony_ci					 "}\n";
360e5c31af7Sopenharmony_ci	test_3.te_body = "${VERSION}\n"
361e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
362e5c31af7Sopenharmony_ci					 "\n"
363e5c31af7Sopenharmony_ci					 "layout(triangles, fractional_odd_spacing, ccw, point_mode) in;\n"
364e5c31af7Sopenharmony_ci					 "\n"
365e5c31af7Sopenharmony_ci					 "void main()\n"
366e5c31af7Sopenharmony_ci					 "{\n"
367e5c31af7Sopenharmony_ci					 "    gl_Position = gl_in[0].gl_Position;\n"
368e5c31af7Sopenharmony_ci					 "}\n";
369e5c31af7Sopenharmony_ci
370e5c31af7Sopenharmony_ci	/* Test 4: 8 vertices per patch + quads + equal_spacing + ccw combination + point mode*/
371e5c31af7Sopenharmony_ci	_test_descriptor test_4;
372e5c31af7Sopenharmony_ci
373e5c31af7Sopenharmony_ci	test_4.expected_control_output_vertices_value = 8;
374e5c31af7Sopenharmony_ci	test_4.expected_gen_mode_value				  = m_glExtTokens.QUADS;
375e5c31af7Sopenharmony_ci	test_4.expected_gen_point_mode_value		  = GL_TRUE;
376e5c31af7Sopenharmony_ci	test_4.expected_gen_spacing_value			  = GL_EQUAL;
377e5c31af7Sopenharmony_ci	test_4.expected_gen_vertex_order_value		  = GL_CCW;
378e5c31af7Sopenharmony_ci	test_4.tc_body								  = "${VERSION}\n"
379e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
380e5c31af7Sopenharmony_ci					 "\n"
381e5c31af7Sopenharmony_ci					 "layout(vertices=8) out;\n"
382e5c31af7Sopenharmony_ci					 "\n"
383e5c31af7Sopenharmony_ci					 "void main()\n"
384e5c31af7Sopenharmony_ci					 "{\n"
385e5c31af7Sopenharmony_ci					 "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
386e5c31af7Sopenharmony_ci					 "}\n";
387e5c31af7Sopenharmony_ci	test_4.te_body = "${VERSION}\n"
388e5c31af7Sopenharmony_ci					 "${TESSELLATION_SHADER_REQUIRE}\n"
389e5c31af7Sopenharmony_ci					 "\n"
390e5c31af7Sopenharmony_ci					 "layout(quads, equal_spacing, ccw, point_mode) in;\n"
391e5c31af7Sopenharmony_ci					 "\n"
392e5c31af7Sopenharmony_ci					 "void main()\n"
393e5c31af7Sopenharmony_ci					 "{\n"
394e5c31af7Sopenharmony_ci					 "    gl_Position = gl_in[0].gl_Position;\n"
395e5c31af7Sopenharmony_ci					 "}\n";
396e5c31af7Sopenharmony_ci
397e5c31af7Sopenharmony_ci	/* Store all tests in a single vector */
398e5c31af7Sopenharmony_ci	_tests tests;
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci	tests.push_back(test_1);
401e5c31af7Sopenharmony_ci	tests.push_back(test_2);
402e5c31af7Sopenharmony_ci	tests.push_back(test_3);
403e5c31af7Sopenharmony_ci	tests.push_back(test_4);
404e5c31af7Sopenharmony_ci
405e5c31af7Sopenharmony_ci	/* Iterate through all the tests and verify the values reported */
406e5c31af7Sopenharmony_ci	for (_tests_const_iterator test_iterator = tests.begin(); test_iterator != tests.end(); test_iterator++)
407e5c31af7Sopenharmony_ci	{
408e5c31af7Sopenharmony_ci		const _test_descriptor& test = *test_iterator;
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci		/* Set tessellation control & evaluation shader bodies. */
411e5c31af7Sopenharmony_ci		shaderSourceSpecialized(m_tc_id, 1 /* count */, &test.tc_body);
412e5c31af7Sopenharmony_ci		shaderSourceSpecialized(m_te_id, 1 /* count */, &test.te_body);
413e5c31af7Sopenharmony_ci
414e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed");
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_ci		/* Compile the shaders */
417e5c31af7Sopenharmony_ci		gl.compileShader(m_tc_id);
418e5c31af7Sopenharmony_ci		gl.compileShader(m_te_id);
419e5c31af7Sopenharmony_ci
420e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
421e5c31af7Sopenharmony_ci
422e5c31af7Sopenharmony_ci		/* Make sure the shaders compiled */
423e5c31af7Sopenharmony_ci		glw::GLint tc_compile_status = GL_FALSE;
424e5c31af7Sopenharmony_ci		glw::GLint te_compile_status = GL_FALSE;
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci		gl.getShaderiv(m_tc_id, GL_COMPILE_STATUS, &tc_compile_status);
427e5c31af7Sopenharmony_ci		gl.getShaderiv(m_te_id, GL_COMPILE_STATUS, &te_compile_status);
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci		if (tc_compile_status != GL_TRUE)
432e5c31af7Sopenharmony_ci		{
433e5c31af7Sopenharmony_ci			TCU_FAIL("Could not compile tessellation control shader");
434e5c31af7Sopenharmony_ci		}
435e5c31af7Sopenharmony_ci
436e5c31af7Sopenharmony_ci		if (te_compile_status != GL_TRUE)
437e5c31af7Sopenharmony_ci		{
438e5c31af7Sopenharmony_ci			TCU_FAIL("Could not compile tessellation evaluation shader");
439e5c31af7Sopenharmony_ci		}
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci		/* Try to link the program object */
442e5c31af7Sopenharmony_ci		glw::GLint link_status = GL_FALSE;
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci		gl.linkProgram(m_po_id);
445e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
446e5c31af7Sopenharmony_ci
447e5c31af7Sopenharmony_ci		gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
448e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_ci		if (link_status != GL_TRUE)
451e5c31af7Sopenharmony_ci		{
452e5c31af7Sopenharmony_ci			TCU_FAIL("Program linking failed");
453e5c31af7Sopenharmony_ci		}
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci		/* Query the tessellation properties of the program object and make sure
456e5c31af7Sopenharmony_ci		 * the values reported are valid */
457e5c31af7Sopenharmony_ci		glw::GLint control_output_vertices_value = 0;
458e5c31af7Sopenharmony_ci		glw::GLint gen_mode_value				 = GL_NONE;
459e5c31af7Sopenharmony_ci		glw::GLint gen_spacing_value			 = GL_NONE;
460e5c31af7Sopenharmony_ci		glw::GLint gen_vertex_order_value		 = GL_NONE;
461e5c31af7Sopenharmony_ci		glw::GLint gen_point_mode_value			 = GL_NONE;
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci		gl.getProgramiv(m_po_id, m_glExtTokens.TESS_CONTROL_OUTPUT_VERTICES, &control_output_vertices_value);
464e5c31af7Sopenharmony_ci		gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_MODE, &gen_mode_value);
465e5c31af7Sopenharmony_ci		gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_SPACING, &gen_spacing_value);
466e5c31af7Sopenharmony_ci		gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_POINT_MODE, &gen_point_mode_value);
467e5c31af7Sopenharmony_ci		gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_VERTEX_ORDER, &gen_vertex_order_value);
468e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() for tessellation-specific properties failed.");
469e5c31af7Sopenharmony_ci
470e5c31af7Sopenharmony_ci		if (control_output_vertices_value != test.expected_control_output_vertices_value)
471e5c31af7Sopenharmony_ci		{
472e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message
473e5c31af7Sopenharmony_ci							   << "Invalid value reported for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT property; "
474e5c31af7Sopenharmony_ci							   << " expected: " << test.expected_control_output_vertices_value
475e5c31af7Sopenharmony_ci							   << ", retrieved: " << control_output_vertices_value << tcu::TestLog::EndMessage;
476e5c31af7Sopenharmony_ci
477e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT property.");
478e5c31af7Sopenharmony_ci		}
479e5c31af7Sopenharmony_ci
480e5c31af7Sopenharmony_ci		if ((glw::GLuint)gen_mode_value != test.expected_gen_mode_value)
481e5c31af7Sopenharmony_ci		{
482e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported for GL_TESS_GEN_MODE_EXT property; "
483e5c31af7Sopenharmony_ci							   << " expected: " << test.expected_gen_mode_value << ", retrieved: " << gen_mode_value
484e5c31af7Sopenharmony_ci							   << tcu::TestLog::EndMessage;
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported for GL_TESS_GEN_MODE_EXT property.");
487e5c31af7Sopenharmony_ci		}
488e5c31af7Sopenharmony_ci
489e5c31af7Sopenharmony_ci		if ((glw::GLuint)gen_spacing_value != test.expected_gen_spacing_value)
490e5c31af7Sopenharmony_ci		{
491e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message
492e5c31af7Sopenharmony_ci							   << "Invalid value reported for GL_TESS_GEN_SPACING_EXT property; "
493e5c31af7Sopenharmony_ci							   << " expected: " << test.expected_gen_spacing_value
494e5c31af7Sopenharmony_ci							   << ", retrieved: " << gen_spacing_value << tcu::TestLog::EndMessage;
495e5c31af7Sopenharmony_ci
496e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported for GL_TESS_GEN_SPACING_EXT property.");
497e5c31af7Sopenharmony_ci		}
498e5c31af7Sopenharmony_ci
499e5c31af7Sopenharmony_ci		if ((glw::GLuint)gen_point_mode_value != test.expected_gen_point_mode_value)
500e5c31af7Sopenharmony_ci		{
501e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message
502e5c31af7Sopenharmony_ci							   << "Invalid value reported for GL_TESS_GEN_POINT_MODE_EXT property; "
503e5c31af7Sopenharmony_ci							   << " expected: " << test.expected_gen_point_mode_value
504e5c31af7Sopenharmony_ci							   << ", retrieved: " << gen_point_mode_value << tcu::TestLog::EndMessage;
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported for GL_TESS_GEN_POINT_MODE_EXT property.");
507e5c31af7Sopenharmony_ci		}
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_ci		if ((glw::GLuint)gen_vertex_order_value != test.expected_gen_vertex_order_value)
510e5c31af7Sopenharmony_ci		{
511e5c31af7Sopenharmony_ci			m_testCtx.getLog() << tcu::TestLog::Message
512e5c31af7Sopenharmony_ci							   << "Invalid value reported for GL_TESS_GEN_VERTEX_ORDER_EXT property; "
513e5c31af7Sopenharmony_ci							   << " expected: " << test.expected_gen_vertex_order_value
514e5c31af7Sopenharmony_ci							   << ", retrieved: " << gen_vertex_order_value << tcu::TestLog::EndMessage;
515e5c31af7Sopenharmony_ci
516e5c31af7Sopenharmony_ci			TCU_FAIL("Invalid value reported for GL_TESS_GEN_VERTEX_ORDER_EXT property.");
517e5c31af7Sopenharmony_ci		}
518e5c31af7Sopenharmony_ci	} /* for (all test descriptors) */
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_ci	/* All done */
521e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
522e5c31af7Sopenharmony_ci	return STOP;
523e5c31af7Sopenharmony_ci}
524e5c31af7Sopenharmony_ci
525e5c31af7Sopenharmony_ci} /* namespace glcts */
526