1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
3e5c31af7Sopenharmony_ci * -----------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2015-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#include "gluDefs.hpp"
24e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
25e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
26e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
27e5c31af7Sopenharmony_ci#include <math.h>
28e5c31af7Sopenharmony_ci#include <string.h>
29e5c31af7Sopenharmony_ci
30e5c31af7Sopenharmony_ci#include "esextcGeometryShaderQualifiers.hpp"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_cinamespace glcts
33e5c31af7Sopenharmony_ci{
34e5c31af7Sopenharmony_ci/** Constructor
35e5c31af7Sopenharmony_ci *
36e5c31af7Sopenharmony_ci * @param context       Test context
37e5c31af7Sopenharmony_ci * @param name          Test case's name
38e5c31af7Sopenharmony_ci * @param description   Test case's desricption
39e5c31af7Sopenharmony_ci **/
40e5c31af7Sopenharmony_ciGeometryShaderFlatInterpolationTest::GeometryShaderFlatInterpolationTest(Context&			  context,
41e5c31af7Sopenharmony_ci																		 const ExtParameters& extParams,
42e5c31af7Sopenharmony_ci																		 const char* name, const char* description)
43e5c31af7Sopenharmony_ci	: TestCaseBase(context, extParams, name, description)
44e5c31af7Sopenharmony_ci	, m_bo_id(0)
45e5c31af7Sopenharmony_ci	, m_fs_id(0)
46e5c31af7Sopenharmony_ci	, m_gs_id(0)
47e5c31af7Sopenharmony_ci	, m_po_id(0)
48e5c31af7Sopenharmony_ci	, m_vao_id(0)
49e5c31af7Sopenharmony_ci	, m_vs_id(0)
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_ci	/* Nothing to be done here */
52e5c31af7Sopenharmony_ci}
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_ci/** Deinitializes GLES objects created during the test. */
55e5c31af7Sopenharmony_civoid GeometryShaderFlatInterpolationTest::deinit(void)
56e5c31af7Sopenharmony_ci{
57e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ci	/* Deinitialize ES objects */
60e5c31af7Sopenharmony_ci	if (m_bo_id != 0)
61e5c31af7Sopenharmony_ci	{
62e5c31af7Sopenharmony_ci		gl.deleteBuffers(1, &m_bo_id);
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_ci		m_bo_id = 0;
65e5c31af7Sopenharmony_ci	}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ci	if (m_fs_id != 0)
68e5c31af7Sopenharmony_ci	{
69e5c31af7Sopenharmony_ci		gl.deleteShader(m_fs_id);
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci		m_fs_id = 0;
72e5c31af7Sopenharmony_ci	}
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ci	if (m_gs_id != 0)
75e5c31af7Sopenharmony_ci	{
76e5c31af7Sopenharmony_ci		gl.deleteShader(m_gs_id);
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci		m_gs_id = 0;
79e5c31af7Sopenharmony_ci	}
80e5c31af7Sopenharmony_ci
81e5c31af7Sopenharmony_ci	if (m_po_id != 0)
82e5c31af7Sopenharmony_ci	{
83e5c31af7Sopenharmony_ci		gl.deleteProgram(m_po_id);
84e5c31af7Sopenharmony_ci
85e5c31af7Sopenharmony_ci		m_po_id = 0;
86e5c31af7Sopenharmony_ci	}
87e5c31af7Sopenharmony_ci
88e5c31af7Sopenharmony_ci	if (m_vao_id != 0)
89e5c31af7Sopenharmony_ci	{
90e5c31af7Sopenharmony_ci		gl.deleteVertexArrays(1, &m_vao_id);
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ci		m_vao_id = 0;
93e5c31af7Sopenharmony_ci	}
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ci	if (m_vs_id != 0)
96e5c31af7Sopenharmony_ci	{
97e5c31af7Sopenharmony_ci		gl.deleteShader(m_vs_id);
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci		m_vs_id = 0;
100e5c31af7Sopenharmony_ci	}
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ci	/* Deinitialize base implementation */
103e5c31af7Sopenharmony_ci	TestCaseBase::deinit();
104e5c31af7Sopenharmony_ci}
105e5c31af7Sopenharmony_ci
106e5c31af7Sopenharmony_ci/* Initializes a program object to be used for the conformance test. */
107e5c31af7Sopenharmony_civoid GeometryShaderFlatInterpolationTest::initProgram()
108e5c31af7Sopenharmony_ci{
109e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_ci	/* Create shader objects */
112e5c31af7Sopenharmony_ci	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
113e5c31af7Sopenharmony_ci	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
114e5c31af7Sopenharmony_ci	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci	/* Create the program object */
119e5c31af7Sopenharmony_ci	m_po_id = gl.createProgram();
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_ci	/* Set the test program object up */
124e5c31af7Sopenharmony_ci	static const char* fs_code_raw = "${VERSION}\n"
125e5c31af7Sopenharmony_ci									 "\n"
126e5c31af7Sopenharmony_ci									 "precision highp float;\n"
127e5c31af7Sopenharmony_ci									 "\n"
128e5c31af7Sopenharmony_ci									 "out vec4 result;\n"
129e5c31af7Sopenharmony_ci									 "\n"
130e5c31af7Sopenharmony_ci									 "void main()\n"
131e5c31af7Sopenharmony_ci									 "{\n"
132e5c31af7Sopenharmony_ci									 "    result = vec4(1.0);\n"
133e5c31af7Sopenharmony_ci									 "}\n";
134e5c31af7Sopenharmony_ci
135e5c31af7Sopenharmony_ci	static const char* gs_code_raw = "${VERSION}\n"
136e5c31af7Sopenharmony_ci									 "${GEOMETRY_SHADER_REQUIRE}\n"
137e5c31af7Sopenharmony_ci									 "\n"
138e5c31af7Sopenharmony_ci									 "layout(triangles)                in;\n"
139e5c31af7Sopenharmony_ci									 "layout(points, max_vertices = 1) out;\n"
140e5c31af7Sopenharmony_ci									 "\n"
141e5c31af7Sopenharmony_ci									 "flat in int out_vertex[];\n"
142e5c31af7Sopenharmony_ci									 "\n"
143e5c31af7Sopenharmony_ci									 "void main()\n"
144e5c31af7Sopenharmony_ci									 "{\n"
145e5c31af7Sopenharmony_ci									 "    if (out_vertex[0] != 0 || out_vertex[1] != 1 || out_vertex[2] != 2)\n"
146e5c31af7Sopenharmony_ci									 "    {\n"
147e5c31af7Sopenharmony_ci									 "        gl_Position = vec4(0.0);\n"
148e5c31af7Sopenharmony_ci									 "    }\n"
149e5c31af7Sopenharmony_ci									 "    else\n"
150e5c31af7Sopenharmony_ci									 "    {\n"
151e5c31af7Sopenharmony_ci									 "        gl_Position = vec4(1.0);\n"
152e5c31af7Sopenharmony_ci									 "    }\n"
153e5c31af7Sopenharmony_ci									 "    EmitVertex();\n"
154e5c31af7Sopenharmony_ci									 "}\n";
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	static const char* po_varying  = "gl_Position";
157e5c31af7Sopenharmony_ci	static const char* vs_code_raw = "${VERSION}\n"
158e5c31af7Sopenharmony_ci									 "\n"
159e5c31af7Sopenharmony_ci									 "flat out int out_vertex;\n"
160e5c31af7Sopenharmony_ci									 "\n"
161e5c31af7Sopenharmony_ci									 "void main()\n"
162e5c31af7Sopenharmony_ci									 "{\n"
163e5c31af7Sopenharmony_ci									 "    gl_Position = vec4(0.0);\n"
164e5c31af7Sopenharmony_ci									 "    out_vertex  = gl_VertexID;\n"
165e5c31af7Sopenharmony_ci									 "}\n";
166e5c31af7Sopenharmony_ci
167e5c31af7Sopenharmony_ci	std::string fs_code_specialized = TestCaseBase::specializeShader(1, /* parts */
168e5c31af7Sopenharmony_ci																	 &fs_code_raw);
169e5c31af7Sopenharmony_ci	const char* fs_code_specialized_raw = fs_code_specialized.c_str();
170e5c31af7Sopenharmony_ci	std::string gs_code_specialized		= TestCaseBase::specializeShader(1, /* parts */
171e5c31af7Sopenharmony_ci																	 &gs_code_raw);
172e5c31af7Sopenharmony_ci	const char* gs_code_specialized_raw = gs_code_specialized.c_str();
173e5c31af7Sopenharmony_ci	std::string vs_code_specialized		= TestCaseBase::specializeShader(1, /* parts */
174e5c31af7Sopenharmony_ci																	 &vs_code_raw);
175e5c31af7Sopenharmony_ci	const char* vs_code_specialized_raw = vs_code_specialized.c_str();
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci	gl.transformFeedbackVaryings(m_po_id, 1, /* count */
178e5c31af7Sopenharmony_ci								 &po_varying, GL_INTERLEAVED_ATTRIBS);
179e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ci	if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1,				  /* n_sh1_body_parts */
182e5c31af7Sopenharmony_ci									&gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
183e5c31af7Sopenharmony_ci									&vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
184e5c31af7Sopenharmony_ci									&fs_code_specialized_raw))
185e5c31af7Sopenharmony_ci	{
186e5c31af7Sopenharmony_ci		TCU_FAIL("Could not build test program object");
187e5c31af7Sopenharmony_ci	}
188e5c31af7Sopenharmony_ci}
189e5c31af7Sopenharmony_ci
190e5c31af7Sopenharmony_ci/** Executes the test.
191e5c31af7Sopenharmony_ci *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
192e5c31af7Sopenharmony_ci *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
193e5c31af7Sopenharmony_ci *  Note the function throws exception should an error occur!
194e5c31af7Sopenharmony_ci **/
195e5c31af7Sopenharmony_citcu::TestNode::IterateResult GeometryShaderFlatInterpolationTest::iterate(void)
196e5c31af7Sopenharmony_ci{
197e5c31af7Sopenharmony_ci	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
198e5c31af7Sopenharmony_ci	bool				  result = true;
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci	/* This test should only run if EXT_geometry_shader is supported. */
201e5c31af7Sopenharmony_ci	if (!m_is_geometry_shader_extension_supported)
202e5c31af7Sopenharmony_ci	{
203e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
204e5c31af7Sopenharmony_ci	}
205e5c31af7Sopenharmony_ci
206e5c31af7Sopenharmony_ci	/* Set up the buffer object */
207e5c31af7Sopenharmony_ci	gl.genBuffers(1, &m_bo_id);
208e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_ci	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
211e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
212e5c31af7Sopenharmony_ci
213e5c31af7Sopenharmony_ci	gl.bufferData(GL_ARRAY_BUFFER, sizeof(float) * 4, /* components */
214e5c31af7Sopenharmony_ci				  DE_NULL,							  /* data */
215e5c31af7Sopenharmony_ci				  GL_STATIC_DRAW);
216e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
219e5c31af7Sopenharmony_ci					  m_bo_id);
220e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ci	/* Set up the vertex array object */
223e5c31af7Sopenharmony_ci	gl.genVertexArrays(1, &m_vao_id);
224e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
225e5c31af7Sopenharmony_ci
226e5c31af7Sopenharmony_ci	gl.bindVertexArray(m_vao_id);
227e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
228e5c31af7Sopenharmony_ci
229e5c31af7Sopenharmony_ci	/* Set up the test program */
230e5c31af7Sopenharmony_ci	initProgram();
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ci	gl.useProgram(m_po_id);
233e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
234e5c31af7Sopenharmony_ci
235e5c31af7Sopenharmony_ci	gl.beginTransformFeedback(GL_POINTS);
236e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci	/* Draw the input triangle */
239e5c31af7Sopenharmony_ci	gl.drawArrays(GL_TRIANGLES, 0, /* first */
240e5c31af7Sopenharmony_ci				  3);			   /* count */
241e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ci	gl.endTransformFeedback();
244e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
245e5c31af7Sopenharmony_ci
246e5c31af7Sopenharmony_ci	/* Map the BO contents to the process space */
247e5c31af7Sopenharmony_ci	const float* result_bo_data = (const float*)gl.mapBufferRange(GL_ARRAY_BUFFER, 0, /* offset */
248e5c31af7Sopenharmony_ci																  sizeof(float) * 4, GL_MAP_READ_BIT);
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci	if (fabs(result_bo_data[0] - 1.0f) >= 1e-5f || fabs(result_bo_data[1] - 1.0f) >= 1e-5f ||
253e5c31af7Sopenharmony_ci		fabs(result_bo_data[2] - 1.0f) >= 1e-5f || fabs(result_bo_data[3] - 1.0f) >= 1e-5f)
254e5c31af7Sopenharmony_ci	{
255e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Invalid texel data was retrieved." << tcu::TestLog::EndMessage;
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_ci		result = false;
258e5c31af7Sopenharmony_ci	}
259e5c31af7Sopenharmony_ci
260e5c31af7Sopenharmony_ci	gl.unmapBuffer(GL_ARRAY_BUFFER);
261e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
262e5c31af7Sopenharmony_ci
263e5c31af7Sopenharmony_ci	/* All done */
264e5c31af7Sopenharmony_ci	if (result)
265e5c31af7Sopenharmony_ci	{
266e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
267e5c31af7Sopenharmony_ci	}
268e5c31af7Sopenharmony_ci	else
269e5c31af7Sopenharmony_ci	{
270e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
271e5c31af7Sopenharmony_ci	}
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci	return STOP;
274e5c31af7Sopenharmony_ci}
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci} // namespace glcts
277