1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24#include "esextcGeometryShaderInput.hpp"
25
26#include "gluContextInfo.hpp"
27#include "glwEnums.hpp"
28#include "glwFunctions.hpp"
29#include "tcuTestLog.hpp"
30#include <cstring>
31
32namespace glcts
33{
34/* Vertex shader for GeometryShader_gl_in_ArrayContents */
35const char* const GeometryShader_gl_in_ArrayContentsTest::m_vertex_shader_code =
36	"${VERSION}\n"
37	"\n"
38	"     out  vec2 vs_gs_a;\n"
39	"flat out ivec4 vs_gs_b;\n"
40	"\n"
41	"void main()\n"
42	"{\n"
43	"    vs_gs_a = vec2 (gl_VertexID, 0);\n"
44	"    vs_gs_b = ivec4(0,           gl_VertexID, 0, 1);\n"
45	"}\n";
46
47/* Geometry shader for GeometryShader_gl_in_ArrayContents */
48const char* const GeometryShader_gl_in_ArrayContentsTest::m_geometry_shader_preamble_code =
49	"${VERSION}\n"
50	"\n"
51	"${GEOMETRY_SHADER_REQUIRE}\n"
52	"\n"
53	"layout(triangles)                      in;\n"
54	"layout(triangle_strip, max_vertices=3) out;\n"
55	"\n";
56
57const char* const GeometryShader_gl_in_ArrayContentsTest::m_geometry_shader_code =
58	"#ifdef USE_UNSIZED_ARRAYS\n"
59	"         in  vec2 vs_gs_a[];\n"
60	"    flat in ivec4 vs_gs_b[];\n"
61	"#else\n"
62	"         in  vec2 vs_gs_a[3];\n"
63	"    flat in ivec4 vs_gs_b[3];\n"
64	"#endif\n"
65	"\n"
66	"     out  vec2 gs_fs_a;\n"
67	"flat out ivec4 gs_fs_b;\n"
68	"\n"
69	"void main()\n"
70	"{\n"
71	"    gl_Position = vec4(-1, -1, 0, 1);\n"
72	"    gs_fs_a     = vs_gs_a[0];\n"
73	"    gs_fs_b     = vs_gs_b[0];\n"
74	"    EmitVertex();\n"
75	"    \n"
76	"    gl_Position = vec4(-1, 1, 0, 1);\n"
77	"    gs_fs_a     = vs_gs_a[1];\n"
78	"    gs_fs_b     = vs_gs_b[1];\n"
79	"    EmitVertex();\n"
80	"    \n"
81	"    gl_Position = vec4(1, 1, 0, 1);\n"
82	"    gs_fs_a     = vs_gs_a[2];\n"
83	"    gs_fs_b     = vs_gs_b[2];\n"
84	"    EmitVertex();\n"
85	"    \n"
86	"    EndPrimitive();\n"
87	"}\n";
88
89/* Fragment shader for GeometryShader_gl_in_ArrayContents */
90const char* const GeometryShader_gl_in_ArrayContentsTest::m_fragment_shader_code =
91	"${VERSION}\n"
92	"\n"
93	"precision highp float;\n"
94	"\n"
95	"layout(location = 0) out vec4 fs_out_color;\n"
96	"\n"
97	"void main()\n"
98	"{\n"
99	"    fs_out_color = vec4(1, 1, 1, 1);\n"
100	"}\n";
101
102/* Vertex Shader for GeometryShader_gl_in_ArrayLengthTest*/
103const char* const GeometryShader_gl_in_ArrayLengthTest::m_vertex_shader_code =
104	"${VERSION}\n"
105	"\n"
106	"void main()\n"
107	"{\n"
108	"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
109	"}\n";
110
111/* Geometry shader body parts for GeometryShader_gl_in_ArrayLengthTest */
112const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_preamble = "${VERSION}\n"
113																						  "\n"
114																						  "${GEOMETRY_SHADER_REQUIRE}\n"
115																						  "\n";
116
117const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_points =
118	"layout(points)                     in;\n";
119
120const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_lines =
121	"layout(lines)                      in;\n";
122
123const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_lines_with_adjacency =
124	"layout(lines_adjacency)            in;\n";
125
126const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_triangles =
127	"layout(triangles)                  in;\n";
128
129const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_triangles_with_adjacency =
130	"layout(triangles_adjacency)        in;\n";
131
132const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_points =
133	"layout(points, max_vertices=1)     out;\n"
134	"\n"
135	"#define N_OUT_VERTICES (1)\n";
136
137const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_line_strip =
138	"layout(line_strip, max_vertices=2) out;\n"
139	"\n"
140	"#define N_OUT_VERTICES (2)\n";
141
142const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_triangle_strip =
143	"layout(triangle_strip, max_vertices=3) out;\n"
144	"\n"
145	"#define N_OUT_VERTICES (3)\n";
146
147const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_main =
148	"\n"
149	"flat out int in_array_size;\n"
150	"\n"
151	"void main()\n"
152	"{\n"
153	"    for (int n = 0; n < N_OUT_VERTICES; n++)\n"
154	"    {\n"
155	"        in_array_size = gl_in.length();\n"
156	"        EmitVertex();\n"
157	"    }\n"
158	"\n"
159	"    EndPrimitive();\n"
160	"}\n";
161
162/* Fragment Shader for GeometryShader_gl_in_ArrayLengthTest */
163const char* const GeometryShader_gl_in_ArrayLengthTest::m_fragment_shader_code = "${VERSION}\n"
164																				 "\n"
165																				 "precision highp float;\n"
166																				 "\n"
167																				 "void main()\n"
168																				 "{\n"
169																				 "}\n";
170
171/* Vertex Shader for GeometryShader_gl_PointSize_ValueTest */
172const char* const GeometryShader_gl_PointSize_ValueTest::m_vertex_shader_code =
173	"${VERSION}\n"
174	"\n"
175	"void main()\n"
176	"{\n"
177	"    // See test description for explanation of magic numbers\n"
178	"    switch (gl_VertexID)\n"
179	"    {\n"
180	"        case 0:\n"
181	"        {\n"
182	"            gl_Position = vec4(-7.0/8.0, 0, 0, 1);\n"
183	"\n"
184	"            break;\n"
185	"        }\n"
186	"\n"
187	"        case 1:\n"
188	"        {\n"
189	"            gl_Position = vec4(6.0/8.0, 0, 0, 1);\n"
190	"\n"
191	"            break;\n"
192	"        }\n"
193	"    }\n"
194	"\n"
195	"    gl_PointSize = float(2 * (gl_VertexID + 1));\n"
196	"}\n";
197
198/* Geometry Shader for GeometryShader_gl_PointSize_ValueTest */
199const char* const GeometryShader_gl_PointSize_ValueTest::m_geometry_shader_code =
200	"${VERSION}\n"
201	"\n"
202	"${GEOMETRY_SHADER_REQUIRE}\n"
203	"${GEOMETRY_POINT_SIZE_REQUIRE}\n"
204	"\n"
205	"layout(points)                 in;\n"
206	"layout(points, max_vertices=1) out;\n"
207	"\n"
208	"void main()\n"
209	"{\n"
210	"    gl_Position  = gl_in[0].gl_Position;\n"
211	"    gl_PointSize = gl_in[0].gl_PointSize * 2.0;\n"
212	"    EmitVertex();\n"
213	"    \n"
214	"    EndPrimitive();\n"
215	"}\n";
216
217/* Fragment Shader for GeometryShader_gl_PointSize_ValueTest */
218const char* const GeometryShader_gl_PointSize_ValueTest::m_fragment_shader_code =
219	"${VERSION}\n"
220	"\n"
221	"precision highp float;\n"
222	"\n"
223	"layout(location = 0) out vec4 fs_out_color;\n"
224	"\n"
225	"void main()\n"
226	"{\n"
227	"    fs_out_color = vec4(1, 1, 1, 1);\n"
228	"}\n";
229
230/* Vertex Shader for GeometryShader_gl_Position_ValueTest */
231const char* const GeometryShader_gl_Position_ValueTest::m_vertex_shader_code =
232	"${VERSION}\n"
233	"\n"
234	"void main()\n"
235	"{\n"
236	"    gl_Position = vec4(gl_VertexID, gl_VertexID, 0, 1);\n"
237	"\n"
238	"}\n";
239
240/* Geometry Shader for GeometryShader_gl_Position_ValueTest */
241const char* const GeometryShader_gl_Position_ValueTest::m_geometry_shader_code =
242	"${VERSION}\n"
243	"\n"
244	"${GEOMETRY_SHADER_REQUIRE}\n"
245	"${GEOMETRY_POINT_SIZE_REQUIRE}\n"
246	"\n"
247	"layout(points)                 in;\n"
248	"layout(points, max_vertices=1) out;\n"
249	"\n"
250	"void main()\n"
251	"{\n"
252	"    // See test description for discussion on the magic numbers\n"
253	"    gl_Position  = vec4(-1.0 + 4.0/32.0 + gl_in[0].gl_Position.x / 4.0, 0, 0, 1);\n"
254	"    gl_PointSize = 8.0;\n"
255	"    EmitVertex();\n"
256	"\n"
257	"    EndPrimitive();\n"
258	"}\n";
259
260/* Fragment Shader for GeometryShader_gl_Position_ValueTest */
261const char* const GeometryShader_gl_Position_ValueTest::m_fragment_shader_code =
262	"${VERSION}\n"
263	"\n"
264	"precision highp float;\n"
265	"\n"
266	"layout(location = 0) out vec4 fs_out_color;\n"
267	"\n"
268	"void main()\n"
269	"{\n"
270	"    fs_out_color = vec4(1, 1, 1, 1);\n"
271	"}\n";
272
273/* Constants for GeometryShader_gl_in_ArrayContentsTest */
274const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_bytes_emitted_per_vertex =
275	2 * sizeof(glw::GLfloat) + 4 * sizeof(glw::GLint);
276const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_emitted_primitives			  = 1;
277const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_vertices_emitted_per_primitive = 3;
278
279const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_buffer_size =
280	GeometryShader_gl_in_ArrayContentsTest::m_n_bytes_emitted_per_vertex *
281	GeometryShader_gl_in_ArrayContentsTest::m_n_vertices_emitted_per_primitive *
282	GeometryShader_gl_in_ArrayContentsTest::m_n_emitted_primitives;
283
284/* Constants for GeometryShader_gl_in_ArrayLengthTest */
285const glw::GLuint GeometryShader_gl_in_ArrayLengthTest::m_max_primitive_emitted = 6;
286const glw::GLuint GeometryShader_gl_in_ArrayLengthTest::m_buffer_size = sizeof(glw::GLint) * m_max_primitive_emitted;
287
288/* Constants for GeometryShader_gl_PointSize_ValueTest */
289const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_height	 = 16;
290const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_pixel_size = 4;
291const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_width	  = 16;
292
293/* Constants for GeometryShader_gl_Position_ValueTest */
294const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_height	 = 64;
295const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_pixel_size = 4;
296const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_width		 = 64;
297
298/** Constructor
299 *
300 * @param context       Test context
301 * @param name          Test case's name
302 * @param description   Test case's desricption
303 **/
304GeometryShader_gl_in_ArrayContentsTest::GeometryShader_gl_in_ArrayContentsTest(Context&				context,
305																			   const ExtParameters& extParams,
306																			   const char*			name,
307																			   const char*			description)
308	: TestCaseBase(context, extParams, name, description)
309	, m_fragment_shader_id(0)
310	, m_geometry_shader_sized_arrays_id(0)
311	, m_geometry_shader_unsized_arrays_id(0)
312	, m_program_object_sized_arrays_id(0)
313	, m_program_object_unsized_arrays_id(0)
314	, m_vertex_shader_id(0)
315	, m_buffer_object_id(0)
316	, m_vertex_array_object_id(0)
317{
318	/* Nothing to be done here */
319}
320
321/** Initializes GLES objects used during the test.
322 *
323 **/
324void GeometryShader_gl_in_ArrayContentsTest::initTest()
325{
326	/* Varing names */
327	const glw::GLchar* const captured_varyings[] = {
328		"gs_fs_a", "gs_fs_b",
329	};
330
331	/* Number of varings */
332	const glw::GLuint n_captured_varyings_size = sizeof(captured_varyings) / sizeof(captured_varyings[0]);
333
334	/* GL */
335	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
336
337	/* Create program and shaders */
338	m_program_object_sized_arrays_id   = gl.createProgram();
339	m_program_object_unsized_arrays_id = gl.createProgram();
340
341	m_fragment_shader_id				= gl.createShader(GL_FRAGMENT_SHADER);
342	m_geometry_shader_unsized_arrays_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
343	m_geometry_shader_sized_arrays_id   = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
344	m_vertex_shader_id					= gl.createShader(GL_VERTEX_SHADER);
345
346	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
347
348	/* Set up transform feedback */
349	gl.transformFeedbackVaryings(m_program_object_sized_arrays_id, n_captured_varyings_size, captured_varyings,
350								 GL_INTERLEAVED_ATTRIBS);
351	gl.transformFeedbackVaryings(m_program_object_unsized_arrays_id, n_captured_varyings_size, captured_varyings,
352								 GL_INTERLEAVED_ATTRIBS);
353
354	/* Build programs */
355	const char* geometry_shader_unsized_arrays_code[] = { m_geometry_shader_preamble_code,
356														  "#define USE_UNSIZED_ARRAYS\n", m_geometry_shader_code };
357	const char* geometry_shader_sized_arrays_code[] = { m_geometry_shader_preamble_code, m_geometry_shader_code };
358
359	if (false ==
360		buildProgram(m_program_object_unsized_arrays_id, m_fragment_shader_id, 1 /* number of fragment shader parts */,
361					 &m_fragment_shader_code, m_geometry_shader_unsized_arrays_id,
362					 DE_LENGTH_OF_ARRAY(geometry_shader_unsized_arrays_code), geometry_shader_unsized_arrays_code,
363					 m_vertex_shader_id, 1 /* number of vertex shader parts */, &m_vertex_shader_code))
364	{
365		TCU_FAIL("Could not create a program from valid vertex/geometry (unsized arrays version)/fragment shaders");
366	}
367
368	if (false == buildProgram(m_program_object_sized_arrays_id, m_fragment_shader_id,
369							  1 /* number of fragment shader parts */, &m_fragment_shader_code,
370							  m_geometry_shader_sized_arrays_id, DE_LENGTH_OF_ARRAY(geometry_shader_sized_arrays_code),
371							  geometry_shader_sized_arrays_code, m_vertex_shader_id,
372							  1 /* number of vertex shader parts */, &m_vertex_shader_code))
373	{
374		TCU_FAIL("Could not create a program from valid vertex/geometry (sized arrays version)/fragment shaders");
375	}
376
377	/* Generate, bind and allocate buffer */
378	gl.genBuffers(1, &m_buffer_object_id);
379	gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
380	gl.bufferData(GL_ARRAY_BUFFER, m_buffer_size, 0 /* no start data */, GL_STATIC_DRAW);
381
382	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create buffer object");
383
384	/* Generate and bind VAO */
385	gl.genVertexArrays(1, &m_vertex_array_object_id);
386	gl.bindVertexArray(m_vertex_array_object_id);
387
388	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
389}
390
391/** Executes the test.
392 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
393 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
394 *  Note the function throws exception should an error occur!
395 **/
396tcu::TestCase::IterateResult GeometryShader_gl_in_ArrayContentsTest::iterate()
397{
398	/* This test should only run if EXT_geometry_shader is supported */
399	if (true != m_is_geometry_shader_extension_supported)
400	{
401		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
402	}
403
404	initTest();
405
406	const glw::Functions& gl							= m_context.getRenderContext().getFunctions();
407	unsigned char		  reference_data[m_buffer_size] = { 0 };
408	bool				  result						= true;
409
410	/* Prepare reference data */
411	{
412		glw::GLint*   ivec4_data_ptr;
413		glw::GLfloat* vec2_data_ptr;
414
415		const unsigned int ivec4_offset_from_vertex = 2 * sizeof(glw::GLfloat);
416		const unsigned int vec2_offset_from_vertex  = 0;
417
418		/* Expected data for vertex:
419		 * vec2  = {VertexID, 0.0f}
420		 * ivec4 = {0,        VertexID, 0, 1}
421		 */
422		for (unsigned int vertex_id = 0; vertex_id < m_n_vertices_emitted_per_primitive * m_n_emitted_primitives;
423			 ++vertex_id)
424		{
425			const unsigned int vertex_offset = vertex_id * m_n_bytes_emitted_per_vertex;
426			const unsigned int ivec4_offset  = vertex_offset + ivec4_offset_from_vertex;
427			const unsigned int vec2_offset   = vertex_offset + vec2_offset_from_vertex;
428
429			ivec4_data_ptr = (glw::GLint*)(reference_data + ivec4_offset);
430			vec2_data_ptr  = (glw::GLfloat*)(reference_data + vec2_offset);
431
432			ivec4_data_ptr[0] = 0;
433			ivec4_data_ptr[1] = vertex_id;
434			ivec4_data_ptr[2] = 0;
435			ivec4_data_ptr[3] = 1;
436
437			vec2_data_ptr[0] = (float)vertex_id;
438			vec2_data_ptr[1] = 0.0f;
439		}
440	}
441
442	/* Setup transform feedback */
443	gl.enable(GL_RASTERIZER_DISCARD);
444	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_object_id);
445
446	/* Draw the geometry */
447	for (int n_case = 0; n_case < 2 /* unsized/sized array cases */; ++n_case)
448	{
449		glw::GLuint po_id = (n_case == 0) ? m_program_object_unsized_arrays_id : m_program_object_sized_arrays_id;
450
451		gl.useProgram(po_id);
452		gl.beginTransformFeedback(GL_TRIANGLES);
453		{
454			gl.drawArrays(GL_TRIANGLES, 0 /* first */, 3 /* one triangle */);
455		}
456		gl.endTransformFeedback();
457
458		GLU_EXPECT_NO_ERROR(gl.getError(), "Error doing a draw call");
459
460		/* Map buffer object storage holding XFB result into process space. */
461		glw::GLchar* transform_feedback_data = (glw::GLchar*)gl.mapBufferRange(
462			GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, m_buffer_size, GL_MAP_READ_BIT);
463
464		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map the buffer object into process space");
465
466		/* Verify data extracted from transform feedback */
467		if (0 != memcmp(transform_feedback_data, reference_data, m_buffer_size))
468		{
469			m_testCtx.getLog() << tcu::TestLog::Message << "Data extracted from transform feedback is invalid."
470							   << tcu::TestLog::EndMessage;
471
472			result = false;
473		}
474
475		/* Unmap the buffer object. */
476		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
477
478		GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping the buffer object");
479
480		/* Verify results */
481		if (true != result)
482		{
483			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
484			return STOP;
485		}
486	}
487
488	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
489	return STOP;
490}
491
492/** Deinitializes GLES objects created during the test.
493 *
494 */
495void GeometryShader_gl_in_ArrayContentsTest::deinit()
496{
497	/* GL */
498	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
499
500	/* Bind default values */
501	gl.useProgram(0);
502	gl.bindVertexArray(0);
503	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, 0 /* id */);
504	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
505
506	/* Delete everything */
507	if (0 != m_vertex_array_object_id)
508	{
509		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
510	}
511
512	if (0 != m_buffer_object_id)
513	{
514		gl.deleteBuffers(1, &m_buffer_object_id);
515	}
516
517	if (0 != m_program_object_sized_arrays_id)
518	{
519		gl.deleteProgram(m_program_object_sized_arrays_id);
520	}
521
522	if (0 != m_program_object_unsized_arrays_id)
523	{
524		gl.deleteProgram(m_program_object_unsized_arrays_id);
525	}
526
527	if (0 != m_fragment_shader_id)
528	{
529		gl.deleteShader(m_fragment_shader_id);
530	}
531
532	if (0 != m_geometry_shader_sized_arrays_id)
533	{
534		gl.deleteShader(m_geometry_shader_sized_arrays_id);
535	}
536
537	if (0 != m_geometry_shader_unsized_arrays_id)
538	{
539		gl.deleteShader(m_geometry_shader_unsized_arrays_id);
540	}
541
542	if (0 != m_vertex_shader_id)
543	{
544		gl.deleteShader(m_vertex_shader_id);
545	}
546
547	/* Deinitialize Base */
548	TestCaseBase::deinit();
549}
550
551/** Constructor
552 *
553 * @param context       Test context
554 * @param name          Test case's name
555 * @param description   Test case's desricption
556 **/
557GeometryShader_gl_in_ArrayLengthTest::GeometryShader_gl_in_ArrayLengthTest(Context&				context,
558																		   const ExtParameters& extParams,
559																		   const char* name, const char* description)
560	: TestCaseBase(context, extParams, name, description), m_buffer_object_id(0), m_vertex_array_object_id(0)
561{
562	/* Nothing to be done here */
563}
564
565/** Initialize test case
566 *
567 **/
568void GeometryShader_gl_in_ArrayLengthTest::init()
569{
570	/* Initialize Base */
571	TestCaseBase::init();
572
573	/* Captured variables */
574	const char* captured_varyings[] = { "in_array_size" };
575
576	/* This test should only run if EXT_geometry_shader is supported */
577	if (true != m_is_geometry_shader_extension_supported)
578	{
579		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
580	}
581
582	/* GL */
583	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
584
585	/* Set up test descriptors */
586	initCase(m_test_lines, GL_LINES, 2, /* number of vertices */
587			 2,							/* as per spec */
588			 GL_POINTS, m_geometry_shader_code_input_lines, m_geometry_shader_code_output_points);
589
590	m_tests.push_back(&m_test_lines);
591
592	initCase(m_test_lines_adjacency, m_glExtTokens.LINES_ADJACENCY, 4, /* number of vertices */
593			 4,														   /* as per spec */
594			 GL_POINTS, m_geometry_shader_code_input_lines_with_adjacency, m_geometry_shader_code_output_points);
595
596	m_tests.push_back(&m_test_lines_adjacency);
597
598	initCase(m_test_points, GL_POINTS, 1, /* number of vertices */
599			 1,							  /* as per spec */
600			 GL_POINTS, m_geometry_shader_code_input_points, m_geometry_shader_code_output_points);
601
602	m_tests.push_back(&m_test_points);
603
604	initCase(m_test_triangles, GL_TRIANGLES, 3, /* number of vertices */
605			 3,									/* as per spec */
606			 GL_POINTS, m_geometry_shader_code_input_triangles, m_geometry_shader_code_output_points);
607
608	m_tests.push_back(&m_test_triangles);
609
610	initCase(m_test_triangles_adjacency, m_glExtTokens.TRIANGLE_STRIP_ADJACENCY, 6, /* number of vertices */
611			 6,																		/* as per spec */
612			 GL_POINTS, m_geometry_shader_code_input_triangles_with_adjacency, m_geometry_shader_code_output_points);
613
614	m_tests.push_back(&m_test_triangles_adjacency);
615
616	initCase(m_test_lines_adjacency_to_line_strip, m_glExtTokens.LINES_ADJACENCY, 4 /* number of vertices */,
617			 4 /* expected array length */, GL_LINES, m_geometry_shader_code_input_lines_with_adjacency,
618			 m_geometry_shader_code_output_line_strip);
619
620	m_tests.push_back(&m_test_lines_adjacency_to_line_strip);
621
622	initCase(m_test_triangles_adjacency_to_triangle_strip, m_glExtTokens.TRIANGLE_STRIP_ADJACENCY,
623			 6 /* number of vertices */, 6 /* expected array length */, GL_TRIANGLES,
624			 m_geometry_shader_code_input_triangles_with_adjacency, m_geometry_shader_code_output_triangle_strip);
625
626	m_tests.push_back(&m_test_triangles_adjacency_to_triangle_strip);
627
628	/* Initialize program objects */
629	for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
630	{
631		/* Case instance */
632		Case* test = *it;
633
634		/* Init program */
635		initCaseProgram(*test, captured_varyings, sizeof(captured_varyings) / sizeof(captured_varyings[0]));
636	}
637
638	/* Generate, bind and allocate buffer */
639	gl.genBuffers(1, &m_buffer_object_id);
640	gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
641	gl.bufferData(GL_ARRAY_BUFFER, m_buffer_size, 0 /* no start data */, GL_STATIC_DRAW);
642
643	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create buffer object");
644
645	/* Generate and bind VAO */
646	gl.genVertexArrays(1, &m_vertex_array_object_id);
647	gl.bindVertexArray(m_vertex_array_object_id);
648
649	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
650}
651
652/** Executes the test.
653 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
654 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
655 *  Note the function throws exception should an error occur!
656 **/
657tcu::TestCase::IterateResult GeometryShader_gl_in_ArrayLengthTest::iterate()
658{
659	/* GL */
660	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
661
662	/* This test should only run if EXT_geometry_shader is supported */
663	if (true != m_is_geometry_shader_extension_supported)
664	{
665		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
666	}
667
668	/* Setup transform feedback */
669	gl.enable(GL_RASTERIZER_DISCARD);
670	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_object_id);
671
672	/* Execute tests */
673	for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
674	{
675		glw::GLint result_value = 0;
676		Case*	  test			= *it;
677
678		/* Execute */
679		gl.useProgram(test->po_id);
680
681		gl.beginTransformFeedback(test->tf_mode);
682		{
683			gl.drawArrays(test->draw_call_mode, 0, /* first */
684						  test->draw_call_n_vertices);
685		}
686		gl.endTransformFeedback();
687
688		GLU_EXPECT_NO_ERROR(gl.getError(), "Error doing a draw call");
689
690		/* Map transform feedback results */
691		glw::GLint* result = (glw::GLint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */,
692															sizeof(glw::GLint), GL_MAP_READ_BIT);
693
694		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map the buffer object into process space");
695
696		/* Extract value from transform feedback */
697		result_value = *result;
698
699		/* Unmap transform feedback buffer */
700		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
701
702		GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping the buffer object");
703
704		/* Verify results */
705		if (result_value != test->expected_array_length)
706		{
707			m_testCtx.getLog() << tcu::TestLog::Message << "Expected array length: " << test->expected_array_length
708							   << " but found: " << result_value << tcu::TestLog::EndMessage;
709
710			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
711			return STOP;
712		}
713	}
714
715	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
716	return STOP;
717}
718
719/** Deinitializes test case
720 *
721 **/
722void GeometryShader_gl_in_ArrayLengthTest::deinit()
723{
724	/* GL */
725	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
726
727	/* Bind default values */
728	gl.useProgram(0);
729	gl.bindVertexArray(0);
730	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, 0 /* id */);
731	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
732
733	/* Delete everything */
734	if (0 != m_vertex_array_object_id)
735	{
736		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
737	}
738
739	if (0 != m_buffer_object_id)
740	{
741		gl.deleteBuffers(1, &m_buffer_object_id);
742	}
743
744	/* Deinit test cases */
745	for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
746	{
747		Case* test = *it;
748
749		deinitCase(*test);
750	}
751
752	m_tests.clear();
753
754	/* Deinitialize Base */
755	TestCaseBase::deinit();
756}
757
758/** Deinitialize test case instance
759 *
760 * @param info Case instance
761 **/
762void GeometryShader_gl_in_ArrayLengthTest::deinitCase(Case& info)
763{
764	/* GL */
765	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
766
767	/* Delete everything */
768	if (0 != info.po_id)
769	{
770		gl.deleteProgram(info.po_id);
771	}
772
773	if (0 != info.vs_id)
774	{
775		gl.deleteShader(info.vs_id);
776	}
777
778	if (0 != info.gs_id)
779	{
780		gl.deleteShader(info.gs_id);
781	}
782
783	if (0 != info.fs_id)
784	{
785		gl.deleteShader(info.fs_id);
786	}
787
788	/* Clear case */
789	resetCase(info);
790}
791
792/** Initialize test case instance with provided data.
793 *
794 * @param info                  Case instance;
795 * @param draw_call_mode        Primitive type used by a draw call;
796 * @param draw_call_n_vertices  Number of vertices used by a draw call;
797 * @param expected_array_length Expected size of gl_in array;
798 * @param tf_mode               Primitive type used by transform feedback;
799 * @param input_body_part       Part of geometry shader which specifies input layout;
800 * @param output_body_part      Part of geometry shader which specifies output layout;
801 **/
802void GeometryShader_gl_in_ArrayLengthTest::initCase(Case& info, glw::GLenum draw_call_mode,
803													glw::GLint draw_call_n_vertices, glw::GLint expected_array_length,
804													glw::GLenum tf_mode, const glw::GLchar* input_body_part,
805													const glw::GLchar* output_body_part)
806{
807	/* Reset case descriptor */
808	resetCase(info);
809
810	/* Set fields */
811	info.draw_call_mode		   = draw_call_mode;
812	info.draw_call_n_vertices  = draw_call_n_vertices;
813	info.expected_array_length = expected_array_length;
814	info.input_body_part	   = input_body_part;
815	info.output_body_part	  = output_body_part;
816	info.tf_mode			   = tf_mode;
817}
818
819/** Creates and build program for given Case
820 *
821 * @param info                     Case instance
822 * @param captured_varyings        Name of varyings captured by transform feedback
823 * @param n_captured_varyings_size Number of varyings captured by transform feedback
824 **/
825void GeometryShader_gl_in_ArrayLengthTest::initCaseProgram(Case& info, const glw::GLchar** captured_varyings,
826														   glw::GLuint n_captured_varyings_size)
827{
828	/* GL */
829	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
830
831	/* Create program and shader objects */
832	info.po_id = gl.createProgram();
833
834	info.vs_id = gl.createShader(GL_VERTEX_SHADER);
835	info.gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
836	info.fs_id = gl.createShader(GL_FRAGMENT_SHADER);
837
838	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object");
839
840	/* Prepare geometry shader parts */
841	const char* const geometry_shader_parts[] = { m_geometry_shader_code_preamble, info.input_body_part,
842												  info.output_body_part, m_geometry_shader_code_main };
843
844	/* Set up transform feedback */
845	gl.transformFeedbackVaryings(info.po_id, n_captured_varyings_size, captured_varyings, GL_SEPARATE_ATTRIBS);
846
847	/* Build program */
848	if (false == buildProgram(info.po_id, info.fs_id, 1 /* number of fragment shader code parts */,
849							  &m_fragment_shader_code, info.gs_id, DE_LENGTH_OF_ARRAY(geometry_shader_parts),
850							  geometry_shader_parts, info.vs_id, 1 /* number of vertex shader code parts */,
851							  &m_vertex_shader_code))
852	{
853		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
854	}
855}
856
857/** Reset Case instance descriptor's contents.
858 *
859 * @param info Case instance
860 **/
861void GeometryShader_gl_in_ArrayLengthTest::resetCase(Case& info)
862{
863	memset(&info, 0, sizeof(info));
864}
865
866/** Constructor
867 *
868 * @param context     Test context
869 * @param name        Test case's name
870 * @param description Test case's desricption
871 **/
872GeometryShader_gl_PointSize_ValueTest::GeometryShader_gl_PointSize_ValueTest(Context&			  context,
873																			 const ExtParameters& extParams,
874																			 const char* name, const char* description)
875	: TestCaseBase(context, extParams, name, description)
876	, m_fragment_shader_id(0)
877	, m_geometry_shader_id(0)
878	, m_program_object_id(0)
879	, m_vertex_shader_id(0)
880	, m_vertex_array_object_id(0)
881	, m_color_texture_id(0)
882	, m_framebuffer_object_id(0)
883{
884	/* Nothing to be done here */
885}
886
887/** Initialize test case
888 *
889 **/
890void GeometryShader_gl_PointSize_ValueTest::init()
891{
892	/* Initialize Base */
893	TestCaseBase::init();
894
895	/* This test should only run if EXT_geometry_shader and EXT_geometry_point_size both are supported */
896	if (true != m_is_geometry_shader_extension_supported)
897	{
898		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
899	}
900
901	if (true != m_is_geometry_shader_point_size_supported)
902	{
903		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
904	}
905
906	/* GL */
907	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
908
909	/* Verify that point size range is supported */
910	glw::GLfloat point_size_range[2] = { 0 };
911
912	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
913	{
914		gl.getFloatv(GL_POINT_SIZE_RANGE, point_size_range);
915	}
916	else
917	{
918		gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, point_size_range);
919	}
920
921	if (8.0f > point_size_range[1])
922	{
923		m_testCtx.getLog() << tcu::TestLog::Message
924						   << "Test requires a minimum maximum point size of 8, implementation reports a maximum of : "
925						   << point_size_range[1] << tcu::TestLog::EndMessage;
926
927		throw tcu::NotSupportedError("Not supported point size", "", __FILE__, __LINE__);
928	}
929
930	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
931	{
932		gl.enable(GL_PROGRAM_POINT_SIZE);
933	}
934
935	/* Create program and shaders */
936	m_program_object_id = gl.createProgram();
937
938	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
939	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
940	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
941
942	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
943
944	/* Build program */
945	if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1 /* fragment shader parts number */,
946							  &m_fragment_shader_code, m_geometry_shader_id, 1 /* geometry shader parts number */,
947							  &m_geometry_shader_code, m_vertex_shader_id, 1 /* vertex shader parts number */,
948							  &m_vertex_shader_code))
949	{
950		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
951	}
952
953	/* Set up texture object and a FBO */
954	gl.genTextures(1, &m_color_texture_id);
955	gl.genFramebuffers(1, &m_framebuffer_object_id);
956
957	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
958
959	if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
960														 m_texture_width, m_texture_height))
961	{
962		TCU_FAIL("Failed to setup framebuffer");
963	}
964
965	/* Set up a vertex array object */
966	gl.genVertexArrays(1, &m_vertex_array_object_id);
967	gl.bindVertexArray(m_vertex_array_object_id);
968
969	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
970}
971
972/** Executes the test.
973 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
974 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
975 *  Note the function throws exception should an error occur!
976 **/
977tcu::TestCase::IterateResult GeometryShader_gl_PointSize_ValueTest::iterate()
978{
979	/* Buffer to store results of rendering */
980	unsigned char result_image[m_texture_width * m_texture_height * m_texture_pixel_size];
981
982	/* This test should only run if EXT_geometry_shader is supported */
983	if (true != m_is_geometry_shader_extension_supported)
984	{
985		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
986	}
987
988	if (true != m_is_geometry_shader_point_size_supported)
989	{
990		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
991	}
992
993	/* GL  */
994	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
995
996	/* Render */
997	gl.useProgram(m_program_object_id);
998
999	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to use program");
1000
1001	gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
1002	gl.clear(GL_COLOR_BUFFER_BIT);
1003
1004	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
1005
1006	gl.drawArrays(GL_POINTS, 0 /* first */, 2 /* count */);
1007
1008	GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
1009
1010	/* Check if the data was modified during the rendering process */
1011	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
1012
1013	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
1014
1015	/* 1) pixel at (2,  8) is (255, 255, 255, 255) */
1016	unsigned int referencePixelCoordinates[2] = { 2, 8 };
1017
1018	if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1019							  m_texture_width, m_texture_height, m_texture_pixel_size, 255 /* red */, 255 /* green */,
1020							  255 /* blue */, 255 /* alpha */))
1021	{
1022		const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1023										  referencePixelCoordinates[0] * m_texture_pixel_size;
1024
1025		m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1026						   << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1027						   << result_image[texel_offset + 3] << "]"
1028						   << " is different from reference data [255, 255, 255, 255]!" << tcu::TestLog::EndMessage;
1029
1030		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1031		return STOP;
1032	}
1033
1034	/* 2) pixel at (14, 8) is (255, 255, 255, 255) */
1035	referencePixelCoordinates[0] = 14;
1036	referencePixelCoordinates[1] = 8;
1037
1038	if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1039							  m_texture_width, m_texture_height, m_texture_pixel_size, 255 /* red */, 255 /* green */,
1040							  255 /* blue */, 255 /* alpha */))
1041	{
1042		const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1043										  referencePixelCoordinates[0] * m_texture_pixel_size;
1044
1045		m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1046						   << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1047						   << result_image[texel_offset + 3] << "]"
1048						   << " is different from reference data [255, 255, 255, 255]!" << tcu::TestLog::EndMessage;
1049
1050		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1051		return STOP;
1052	}
1053
1054	/* 3) pixel at (6,  8) is (0,   0,   0,   0) */
1055	referencePixelCoordinates[0] = 6;
1056	referencePixelCoordinates[1] = 8;
1057
1058	if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1059							  m_texture_width, m_texture_height, m_texture_pixel_size, 0 /* red */, 0 /* green */,
1060							  0 /* blue */, 0 /* alpha */))
1061	{
1062		const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1063										  referencePixelCoordinates[0] * m_texture_pixel_size;
1064
1065		m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1066						   << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1067						   << result_image[texel_offset + 3] << "]"
1068						   << "is different from reference data [0, 0, 0, 0]!" << tcu::TestLog::EndMessage;
1069
1070		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1071		return STOP;
1072	}
1073
1074	/* Done */
1075	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1076	return STOP;
1077}
1078
1079/** Deinitializes test case
1080 *
1081 **/
1082void GeometryShader_gl_PointSize_ValueTest::deinit()
1083{
1084	/* GL */
1085	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1086
1087	/* Bind defaults */
1088	gl.useProgram(0);
1089	gl.bindVertexArray(0);
1090	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture */, 0 /* level */);
1091	gl.bindTexture(GL_TEXTURE_2D, 0);
1092	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1093	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1094	{
1095		gl.disable(GL_PROGRAM_POINT_SIZE);
1096	}
1097
1098	/* Delete everything */
1099	if (m_program_object_id != 0)
1100	{
1101		gl.deleteProgram(m_program_object_id);
1102	}
1103
1104	if (m_fragment_shader_id != 0)
1105	{
1106		gl.deleteShader(m_fragment_shader_id);
1107	}
1108
1109	if (m_geometry_shader_id != 0)
1110	{
1111		gl.deleteShader(m_geometry_shader_id);
1112	}
1113
1114	if (m_vertex_shader_id != 0)
1115	{
1116		gl.deleteShader(m_vertex_shader_id);
1117	}
1118
1119	if (m_vertex_array_object_id != 0)
1120	{
1121		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1122	}
1123
1124	if (m_color_texture_id != 0)
1125	{
1126		gl.deleteTextures(1, &m_color_texture_id);
1127	}
1128
1129	if (m_framebuffer_object_id != 0)
1130	{
1131		gl.deleteFramebuffers(1, &m_framebuffer_object_id);
1132	}
1133
1134	/* Release base class */
1135	TestCaseBase::deinit();
1136}
1137
1138/** Constructor
1139 *
1140 * @param context     Test context
1141 * @param name        Test case's name
1142 * @param description Test case's desricption
1143 **/
1144GeometryShader_gl_Position_ValueTest::GeometryShader_gl_Position_ValueTest(Context&				context,
1145																		   const ExtParameters& extParams,
1146																		   const char* name, const char* description)
1147	: TestCaseBase(context, extParams, name, description)
1148	, m_fragment_shader_id(0)
1149	, m_geometry_shader_id(0)
1150	, m_program_object_id(0)
1151	, m_vertex_shader_id(0)
1152	, m_vertex_array_object_id(0)
1153	, m_color_texture_id(0)
1154	, m_framebuffer_object_id(0)
1155{
1156	/* Nothing to be done here */
1157}
1158
1159/** Initialize test case
1160 *
1161 **/
1162void GeometryShader_gl_Position_ValueTest::init()
1163{
1164	/* Initialize base */
1165	TestCaseBase::init();
1166
1167	/* This test should only run if EXT_geometry_shader is supported */
1168	if (true != m_is_geometry_shader_extension_supported)
1169	{
1170		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1171	}
1172
1173	if (true != m_is_geometry_shader_point_size_supported)
1174	{
1175		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
1176	}
1177
1178	/* GL */
1179	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1180
1181	/* Verify that point size range is supported */
1182	glw::GLfloat point_size_range[2] = { 0 };
1183
1184	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1185	{
1186		gl.getFloatv(GL_POINT_SIZE_RANGE, point_size_range);
1187	}
1188	else
1189	{
1190		gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, point_size_range);
1191	}
1192
1193	if (8.0f > point_size_range[1])
1194	{
1195		m_testCtx.getLog() << tcu::TestLog::Message
1196						   << "Test requires a minimum maximum point size of 8, implementation reports a maximum of : "
1197						   << point_size_range[1] << tcu::TestLog::EndMessage;
1198
1199		throw tcu::NotSupportedError("Not supported point size", "", __FILE__, __LINE__);
1200	}
1201
1202	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1203	{
1204		gl.enable(GL_PROGRAM_POINT_SIZE);
1205	}
1206
1207	/* Create program and shaders */
1208	m_program_object_id = gl.createProgram();
1209
1210	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
1211	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1212	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
1213
1214	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
1215
1216	/* Build program */
1217	if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1 /* fragment shader parts number */,
1218							  &m_fragment_shader_code, m_geometry_shader_id, 1 /* geometry shader parts number */,
1219							  &m_geometry_shader_code, m_vertex_shader_id, 1 /* vertex shader parts number */,
1220							  &m_vertex_shader_code))
1221	{
1222		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
1223	}
1224
1225	/* Set up a texture object and a FBO */
1226	gl.genTextures(1, &m_color_texture_id);
1227	gl.genFramebuffers(1, &m_framebuffer_object_id);
1228
1229	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
1230
1231	if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
1232														 m_texture_width, m_texture_height))
1233	{
1234		TCU_FAIL("Failed to setup framebuffer");
1235	}
1236
1237	/* Set up a vertex array object */
1238	gl.genVertexArrays(1, &m_vertex_array_object_id);
1239	gl.bindVertexArray(m_vertex_array_object_id);
1240
1241	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
1242}
1243
1244/** Executes the test.
1245 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1246 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1247 *  Note the function throws exception should an error occur!
1248 **/
1249tcu::TestCase::IterateResult GeometryShader_gl_Position_ValueTest::iterate()
1250{
1251	/* Variables used for image verification purposes */
1252	unsigned char result_image[m_texture_width * m_texture_height * m_texture_pixel_size];
1253
1254	/* This test should only run if EXT_geometry_shader is supported */
1255	if (true != m_is_geometry_shader_extension_supported)
1256	{
1257		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1258	}
1259
1260	/* GL  */
1261	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1262
1263	/* Render */
1264	gl.useProgram(m_program_object_id);
1265
1266	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to use program");
1267
1268	gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
1269	gl.clear(GL_COLOR_BUFFER_BIT);
1270
1271	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
1272
1273	gl.drawArrays(GL_POINTS, 0 /* first */, 8 /* count */);
1274
1275	GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
1276
1277	/* Check if the data was modified during the rendering process */
1278	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
1279
1280	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
1281
1282	/* The test passes if centers of the rendered points are lit at expected locations. */
1283	for (unsigned int x = 4; x < m_texture_width; x += 8)
1284	{
1285		if (false == comparePixel(result_image, x, 32 /* y */, m_texture_width, m_texture_height, m_texture_pixel_size,
1286								  255 /* red */, 255 /* green */, 255 /* blue */, 255 /* alpha */))
1287		{
1288			const unsigned int texel_offset = 32 * m_texture_width * m_texture_pixel_size + x * m_texture_pixel_size;
1289
1290			m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1291							   << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1292							   << result_image[texel_offset + 3] << "]"
1293							   << "is different from reference data [255, 255, 255, 255] !" << tcu::TestLog::EndMessage;
1294
1295			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1296			return STOP;
1297		}
1298	}
1299
1300	/* Done */
1301	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1302	return STOP;
1303}
1304
1305/** Deinitializes test case
1306 *
1307 **/
1308void GeometryShader_gl_Position_ValueTest::deinit()
1309{
1310	/* GL */
1311	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1312
1313	/* Bind default values */
1314	gl.useProgram(0);
1315	gl.bindVertexArray(0);
1316	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture */, 0 /* level */);
1317	gl.bindTexture(GL_TEXTURE_2D, 0);
1318	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1319	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1320	{
1321		gl.disable(GL_PROGRAM_POINT_SIZE);
1322	}
1323
1324	/* Delete everything */
1325	if (m_program_object_id != 0)
1326	{
1327		gl.deleteProgram(m_program_object_id);
1328	}
1329
1330	if (m_fragment_shader_id != 0)
1331	{
1332		gl.deleteShader(m_fragment_shader_id);
1333	}
1334
1335	if (m_geometry_shader_id != 0)
1336	{
1337		gl.deleteShader(m_geometry_shader_id);
1338	}
1339
1340	if (m_vertex_shader_id != 0)
1341	{
1342		gl.deleteShader(m_vertex_shader_id);
1343	}
1344
1345	if (m_vertex_array_object_id != 0)
1346	{
1347		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1348	}
1349
1350	if (m_color_texture_id != 0)
1351	{
1352		gl.deleteTextures(1, &m_color_texture_id);
1353	}
1354
1355	if (m_framebuffer_object_id != 0)
1356	{
1357		gl.deleteFramebuffers(1, &m_framebuffer_object_id);
1358	}
1359
1360	/* Release base class */
1361	TestCaseBase::deinit();
1362}
1363
1364} /* glcts */
1365