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 "esextcGeometryShaderLayeredFramebuffer.hpp"
25
26#include "gluContextInfo.hpp"
27#include "gluDefs.hpp"
28#include "glwEnums.hpp"
29#include "glwFunctions.hpp"
30#include "tcuTestLog.hpp"
31#include <cstring>
32
33namespace glcts
34{
35/** Constructor
36 *
37 * @param context       Test context
38 * @param name          Test case's name
39 * @param description   Test case's desricption
40 **/
41GeometryShaderLayeredFramebufferBlending::GeometryShaderLayeredFramebufferBlending(Context&				context,
42																				   const ExtParameters& extParams,
43																				   const char*			name,
44																				   const char*			description)
45	: TestCaseBase(context, extParams, name, description)
46	, m_fbo_id(0)
47	, m_fs_id(0)
48	, m_gs_id(0)
49	, m_po_id(0)
50	, m_read_fbo_id(0)
51	, m_to_id(0)
52	, m_vao_id(0)
53	, m_vs_id(0)
54{
55	/* Left blank on purpose */
56}
57
58/** Deinitializes GLES objects created during the test. */
59void GeometryShaderLayeredFramebufferBlending::deinit(void)
60{
61	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
62
63	/* Clean up */
64	if (m_fbo_id != 0)
65	{
66		gl.deleteFramebuffers(1, &m_fbo_id);
67	}
68
69	if (m_fs_id != 0)
70	{
71		gl.deleteShader(m_fs_id);
72	}
73
74	if (m_gs_id != 0)
75	{
76		gl.deleteShader(m_gs_id);
77	}
78
79	if (m_po_id != 0)
80	{
81		gl.deleteProgram(m_po_id);
82	}
83
84	if (m_read_fbo_id != 0)
85	{
86		gl.deleteFramebuffers(1, &m_read_fbo_id);
87	}
88
89	if (m_to_id != 0)
90	{
91		gl.deleteTextures(1, &m_to_id);
92	}
93
94	if (m_vao_id != 0)
95	{
96		gl.deleteVertexArrays(1, &m_vao_id);
97	}
98
99	if (m_vs_id != 0)
100	{
101		gl.deleteShader(m_vs_id);
102	}
103
104	/* Release base class */
105	TestCaseBase::deinit();
106}
107
108/** Executes the test.
109 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
110 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
111 *  Note the function throws exception should an error occur!
112 **/
113tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferBlending::iterate(void)
114{
115/* Test-wide constants */
116#define N_TEXTURE_COMPONENTS (4)
117#define TEXTURE_DEPTH (4)
118#define TEXTURE_HEIGHT (4)
119#define TEXTURE_WIDTH (4)
120
121	/* Fragment shader code */
122	const char* fs_code = "${VERSION}\n"
123						  "\n"
124						  "precision highp float;\n"
125						  "\n"
126						  "out vec4 result;\n"
127						  "\n"
128						  "void main()\n"
129						  "{\n"
130						  "    result = vec4(0.2);\n"
131						  "}\n";
132
133	/* Geometry shader code */
134	const char* gs_code = "${VERSION}\n"
135						  "${GEOMETRY_SHADER_REQUIRE}\n"
136						  "\n"
137						  "layout(points)                          in;\n"
138						  "layout(triangle_strip, max_vertices=64) out;\n"
139						  "\n"
140						  "void main()\n"
141						  "{\n"
142						  "    for (int n = 0; n < 4; ++n)\n"
143						  "    {\n"
144						  "        gl_Layer    = n;\n"
145						  "        gl_Position = vec4(1, 1, 0, 1);\n"
146						  "        EmitVertex();\n"
147						  "\n"
148						  "        gl_Layer    = n;\n"
149						  "        gl_Position = vec4(1, -1, 0, 1);\n"
150						  "        EmitVertex();\n"
151						  "\n"
152						  "        gl_Layer    = n;\n"
153						  "        gl_Position = vec4(-1, 1, 0, 1);\n"
154						  "        EmitVertex();\n"
155						  "\n"
156						  "        gl_Layer    = n;\n"
157						  "        gl_Position = vec4(-1, -1, 0, 1);\n"
158						  "        EmitVertex();\n"
159						  "\n"
160						  "        EndPrimitive();\n"
161						  "    }\n"
162						  "}\n";
163
164	/* General variables */
165	const glw::Functions& gl		  = m_context.getRenderContext().getFunctions();
166	unsigned int		  n			  = 0;
167	unsigned int		  n_component = 0;
168	unsigned int		  n_layer	 = 0;
169	unsigned int		  n_slice	 = 0;
170	unsigned int		  x			  = 0;
171	unsigned int		  y			  = 0;
172
173	unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
174	unsigned char buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
175	unsigned char buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
176	unsigned char buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
177	unsigned char buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
178	unsigned char ref_buffer_slice1[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
179	unsigned char ref_buffer_slice2[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
180	unsigned char ref_buffer_slice3[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
181	unsigned char ref_buffer_slice4[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
182
183	if (!m_is_geometry_shader_extension_supported)
184	{
185		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
186	}
187
188	/* Set up shader objects */
189	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
190	m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
191	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
192
193	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate shader objects");
194
195	/* Set up program objects */
196	m_po_id = gl.createProgram();
197
198	if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */,
199					  &m_boilerplate_vs_code))
200	{
201		TCU_FAIL("Could not build program object");
202	}
203
204	/* Prepare texture data we will use for each slice */
205	for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
206	{
207		unsigned char* slice_pixels_ptr[] = { buffer_slice1 + n * N_TEXTURE_COMPONENTS,
208											  buffer_slice2 + n * N_TEXTURE_COMPONENTS,
209											  buffer_slice3 + n * N_TEXTURE_COMPONENTS,
210											  buffer_slice4 + n * N_TEXTURE_COMPONENTS };
211
212		for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice)
213		{
214			slice_pixels_ptr[n_slice][0] = 0;
215			slice_pixels_ptr[n_slice][1] = (unsigned char)(n_slice * 255 / 4);
216			slice_pixels_ptr[n_slice][2] = (unsigned char)(n_slice * 255 / 8);
217			slice_pixels_ptr[n_slice][3] = (unsigned char)(n_slice * 255 / 12);
218		} /* for (all slices) */
219	}	 /* for (all pixels) */
220
221	/* Calculate reference texture data we will later use when verifying the rendered data */
222	for (n = 0; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
223	{
224		unsigned char* ref_slice_pixels_ptr[] = { ref_buffer_slice1 + n * N_TEXTURE_COMPONENTS,
225												  ref_buffer_slice2 + n * N_TEXTURE_COMPONENTS,
226												  ref_buffer_slice3 + n * N_TEXTURE_COMPONENTS,
227												  ref_buffer_slice4 + n * N_TEXTURE_COMPONENTS };
228
229		unsigned char* slice_pixels_ptr[] = { buffer_slice1 + n * N_TEXTURE_COMPONENTS,
230											  buffer_slice2 + n * N_TEXTURE_COMPONENTS,
231											  buffer_slice3 + n * N_TEXTURE_COMPONENTS,
232											  buffer_slice4 + n * N_TEXTURE_COMPONENTS };
233
234		for (n_slice = 0; n_slice < sizeof(slice_pixels_ptr) / sizeof(slice_pixels_ptr[0]); ++n_slice)
235		{
236			unsigned char* ref_slice_ptr = ref_slice_pixels_ptr[n_slice];
237			unsigned char* slice_ptr	 = slice_pixels_ptr[n_slice];
238			float		   slice_rgba[]  = {
239				float(slice_ptr[0]) / 255.0f, /* convert to FP representation */
240				float(slice_ptr[1]) / 255.0f, /* convert to FP representation */
241				float(slice_ptr[2]) / 255.0f, /* convert to FP representation */
242				float(slice_ptr[3]) / 255.0f  /* convert to FP representation */
243			};
244
245			for (n_component = 0; n_component < N_TEXTURE_COMPONENTS; ++n_component)
246			{
247				float temp_component = slice_rgba[n_component] /* dst_color */ * slice_rgba[n_component] /* dst_color */
248									   + 0.8f /* 1-src_color */ * 0.2f /* src_color */;
249
250				/* Clamp if necessary */
251				if (temp_component < 0)
252				{
253					temp_component = 0.0f;
254				}
255				else if (temp_component > 1)
256				{
257					temp_component = 1.0f;
258				}
259
260				/* Convert back to GL_RGBA8 */
261				ref_slice_ptr[n_component] = (unsigned char)(temp_component * 255.0f);
262			} /* for (all components) */
263		}	 /* for (all slices) */
264	}		  /* for (all pixels) */
265
266	/* Set up texture object used for the test */
267	gl.genTextures(1, &m_to_id);
268	gl.bindTexture(GL_TEXTURE_3D, m_to_id);
269	gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
270	gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
271					 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice1);
272	gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
273					 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice2);
274	gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
275					 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice3);
276	gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
277					 TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, buffer_slice4);
278
279	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object");
280
281	/* Set up framebuffer object used for the test */
282	gl.genFramebuffers(1, &m_fbo_id);
283	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
284
285	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */);
286
287	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer");
288
289	/* Generate and bind a vertex array object */
290	gl.genVertexArrays(1, &m_vao_id);
291	gl.bindVertexArray(m_vao_id);
292
293	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up vertex array object");
294
295	/* Set up blending */
296	gl.blendFunc(GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR);
297	gl.enable(GL_BLEND);
298
299	/* Render */
300	gl.useProgram(m_po_id);
301	gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
302
303	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
304
305	GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed");
306
307	/* Verify rendered data in the layers */
308	gl.genFramebuffers(1, &m_read_fbo_id);
309	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
310
311	for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer)
312	{
313		bool has_layer_failed = false;
314
315		const unsigned char* ref_buffer =
316			(n_layer == 0) ?
317				ref_buffer_slice1 :
318				(n_layer == 1) ? ref_buffer_slice2 : (n_layer == 2) ? ref_buffer_slice3 : ref_buffer_slice4;
319
320		gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_id, 0 /* level */, n_layer);
321		gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
322
323		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixel data!");
324
325		for (y = 0; y < TEXTURE_HEIGHT; ++y)
326		{
327			const unsigned int   pixel_size = N_TEXTURE_COMPONENTS;
328			const unsigned char* ref_row	= ref_buffer + y * pixel_size;
329			const unsigned char* row		= buffer + y * pixel_size;
330
331			for (x = 0; x < TEXTURE_WIDTH; ++x)
332			{
333#define EPSILON (1)
334
335				const unsigned char* data	 = row + x * pixel_size;
336				const unsigned char* ref_data = ref_row + x * pixel_size;
337
338				if (de::abs((int)data[0] - (int)ref_data[0]) > EPSILON ||
339					de::abs((int)data[1] - (int)ref_data[1]) > EPSILON ||
340					de::abs((int)data[2] - (int)ref_data[2]) > EPSILON ||
341					de::abs((int)data[3] - (int)ref_data[3]) > EPSILON)
342				{
343					m_testCtx.getLog() << tcu::TestLog::Message << "(layer=" << n_layer << " x=" << x << " y=" << y
344									   << ") "
345									   << "Reference value is different than the rendered data (epsilon > " << EPSILON
346									   << "): "
347									   << "(" << (unsigned int)ref_data[0] << ", " << (unsigned int)ref_data[1] << ", "
348									   << (unsigned int)ref_data[2] << ", " << (unsigned int)ref_data[3] << ") vs "
349									   << "(" << (unsigned int)data[0] << ", " << (unsigned int)data[1] << ", "
350									   << (unsigned int)data[2] << ", " << (unsigned int)data[3] << ")."
351									   << tcu::TestLog::EndMessage;
352
353					has_layer_failed = true;
354				} /* if (regions are different) */
355
356#undef EPSILON
357			} /* for (all pixels in a row) */
358		}	 /* for (all rows) */
359
360		if (has_layer_failed)
361		{
362			TCU_FAIL("Pixel data comparison failed");
363		}
364	} /* for (all layers) */
365
366	/* Done */
367	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
368	return STOP;
369
370#undef N_TEXTURE_COMPONENTS
371#undef TEXTURE_DEPTH
372#undef TEXTURE_HEIGHT
373#undef TEXTURE_WIDTH
374}
375
376/** Constructor
377 *
378 * @param context       Test context
379 * @param name          Test case's name
380 * @param description   Test case's description
381 **/
382GeometryShaderLayeredFramebufferClear::GeometryShaderLayeredFramebufferClear(Context&			  context,
383																			 const ExtParameters& extParams,
384																			 const char* name, const char* description)
385	: TestCaseBase(context, extParams, name, description)
386	, m_fbo_char_id(0)
387	, m_fbo_int_id(0)
388	, m_fbo_uint_id(0)
389	, m_read_fbo_id(0)
390	, m_to_rgba32i_id(0)
391	, m_to_rgba32ui_id(0)
392	, m_to_rgba8_id(0)
393{
394	/* Left blank on purpose */
395}
396
397/** Executes the test.
398 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
399 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
400 *  Note the function throws exception should an error occur!
401 **/
402tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferClear::iterate(void)
403{
404	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
405
406/* Test-wide definitions */
407#define N_TEXTURE_COMPONENTS (4)
408#define TEXTURE_DEPTH (4)
409#define TEXTURE_HEIGHT (4)
410#define TEXTURE_WIDTH (4)
411
412	/* Type definitions */
413	typedef enum {
414		/* Always first */
415		CLEAR_FIRST = 0,
416
417		/* glClear() */
418		CLEAR_PLAIN = CLEAR_FIRST,
419		/* glClearBufferfv() */
420		CLEAR_BUFFERFV,
421		/* glClearBufferiv() */
422		CLEAR_BUFFERIV,
423		/* glClearBufferuiv() */
424		CLEAR_BUFFERUIV,
425
426		/* Always last */
427		CLEAR_COUNT
428	} _clear_type;
429
430	/* General variables */
431	const glw::GLenum fbo_draw_buffer = GL_COLOR_ATTACHMENT0;
432
433	int n		= 0;
434	int n_layer = 0;
435	int x		= 0;
436	int y		= 0;
437
438	unsigned char buffer_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
439	int			  buffer_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
440	unsigned int  buffer_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
441	unsigned char slice_1_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
442	int			  slice_1_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
443	unsigned int  slice_1_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
444	unsigned char slice_2_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
445	int			  slice_2_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
446	unsigned int  slice_2_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
447	unsigned char slice_3_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
448	int			  slice_3_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
449	unsigned int  slice_3_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
450	unsigned char slice_4_data_char[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
451	int			  slice_4_data_int[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
452	unsigned int  slice_4_data_uint[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
453
454	/* Only carry on if geometry shaders are supported */
455	if (!m_is_geometry_shader_extension_supported)
456	{
457		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
458	}
459
460	/* Set up slice data */
461	memset(slice_1_data_char, 0, sizeof(slice_1_data_char));
462	memset(slice_1_data_int, 0, sizeof(slice_1_data_int));
463	memset(slice_1_data_uint, 0, sizeof(slice_1_data_uint));
464	memset(slice_2_data_char, 0, sizeof(slice_2_data_char));
465	memset(slice_2_data_int, 0, sizeof(slice_2_data_int));
466	memset(slice_2_data_uint, 0, sizeof(slice_2_data_uint));
467	memset(slice_3_data_char, 0, sizeof(slice_3_data_char));
468	memset(slice_3_data_int, 0, sizeof(slice_3_data_int));
469	memset(slice_3_data_uint, 0, sizeof(slice_3_data_uint));
470	memset(slice_4_data_char, 0, sizeof(slice_4_data_char));
471	memset(slice_4_data_int, 0, sizeof(slice_4_data_int));
472	memset(slice_4_data_uint, 0, sizeof(slice_4_data_uint));
473
474	for (n = 0; n < 4 /* width */ * 4 /* height */; ++n)
475	{
476		slice_1_data_char[4 * n + 0] = 255;
477		slice_1_data_int[4 * n + 0]  = 255;
478		slice_1_data_uint[4 * n + 0] = 255;
479
480		slice_2_data_char[4 * n + 1] = 255;
481		slice_2_data_int[4 * n + 1]  = 255;
482		slice_2_data_uint[4 * n + 1] = 255;
483
484		slice_3_data_char[4 * n + 2] = 255;
485		slice_3_data_int[4 * n + 2]  = 255;
486		slice_3_data_uint[4 * n + 2] = 255;
487
488		slice_4_data_char[4 * n + 0] = 255;
489		slice_4_data_char[4 * n + 1] = 255;
490		slice_4_data_int[4 * n + 0]  = 255;
491		slice_4_data_int[4 * n + 1]  = 255;
492		slice_4_data_uint[4 * n + 0] = 255;
493		slice_4_data_uint[4 * n + 1] = 255;
494	} /* for (all pixels) */
495
496	/* Set up texture objects */
497	gl.genTextures(1, &m_to_rgba8_id);
498	gl.genTextures(1, &m_to_rgba32i_id);
499	gl.genTextures(1, &m_to_rgba32ui_id);
500
501	for (n = 0; n < 3 /* textures */; ++n)
502	{
503		void* to_data_1 =
504			(n == 0) ? (void*)slice_1_data_char : (n == 1) ? (void*)slice_1_data_int : (void*)slice_1_data_uint;
505
506		void* to_data_2 =
507			(n == 0) ? (void*)slice_2_data_char : (n == 1) ? (void*)slice_2_data_int : (void*)slice_2_data_uint;
508
509		void* to_data_3 =
510			(n == 0) ? (void*)slice_3_data_char : (n == 1) ? (void*)slice_3_data_int : (void*)slice_3_data_uint;
511
512		void* to_data_4 =
513			(n == 0) ? (void*)slice_4_data_char : (n == 1) ? (void*)slice_4_data_int : (void*)slice_4_data_uint;
514
515		glw::GLenum to_format = (n == 0) ? GL_RGBA : (n == 1) ? GL_RGBA_INTEGER : GL_RGBA_INTEGER;
516
517		glw::GLenum to_internalformat = (n == 0) ? GL_RGBA8 : (n == 1) ? GL_RGBA32I : GL_RGBA32UI;
518
519		glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id;
520
521		glw::GLenum to_type = (n == 0) ? GL_UNSIGNED_BYTE : (n == 1) ? GL_INT : GL_UNSIGNED_INT;
522
523		gl.bindTexture(GL_TEXTURE_3D, to_id);
524
525		gl.texStorage3D(GL_TEXTURE_3D, 1 /* levels */, to_internalformat, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
526
527		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
528						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_1);
529		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
530						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_2);
531		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
532						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_3);
533		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
534						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, to_data_4);
535
536		gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
537		gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 0);
538		gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
539
540		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture object");
541	} /* for (all texture objects) */
542
543	/* Set up framebuffer object */
544	gl.genFramebuffers(1, &m_fbo_char_id);
545	gl.genFramebuffers(1, &m_fbo_int_id);
546	gl.genFramebuffers(1, &m_fbo_uint_id);
547	gl.genFramebuffers(1, &m_read_fbo_id);
548
549	for (n = 0; n < 3 /* framebuffers */; ++n)
550	{
551		glw::GLuint fbo_id = (n == 0) ? m_fbo_char_id : (n == 1) ? m_fbo_int_id : m_fbo_uint_id;
552
553		glw::GLuint to_id = (n == 0) ? m_to_rgba8_id : (n == 1) ? m_to_rgba32i_id : m_to_rgba32ui_id;
554
555		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_id);
556		gl.drawBuffers(1, &fbo_draw_buffer);
557		gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */);
558
559		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object");
560	} /* for (all framebuffers) */
561
562	/* Try reading from the layered framebuffer. */
563	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_char_id);
564	gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer_char);
565
566	/* Is the returned data an exact copy of what we've uploaded for layer zero? */
567	if (memcmp(buffer_char, slice_1_data_char, sizeof(slice_1_data_char)) != 0)
568	{
569		TCU_FAIL("Retrieved data is different from data uploaded for layer 0 of a layered framebuffer.");
570	}
571
572	/* Iterate through all clear calls supported */
573
574	for (int current_test = static_cast<int>(CLEAR_FIRST); current_test < static_cast<int>(CLEAR_COUNT); current_test++)
575	{
576		void*				buffer				= NULL;
577		const float			clear_color_float[] = { 0.25f, 0.5f, 1.0f, 32.0f / 255.0f };
578		const int			clear_color_int[]   = { 64, 128, 255, 32 };
579		glw::GLuint			fbo_id				= 0;
580		int					pixel_size			= 0;
581		void*				slice_1_data		= NULL;
582		void*				slice_2_data		= NULL;
583		void*				slice_3_data		= NULL;
584		void*				slice_4_data		= NULL;
585		glw::GLenum			to_format			= GL_NONE;
586		glw::GLuint			to_id				= 0;
587		glw::GLenum			to_type				= GL_NONE;
588
589		switch (static_cast<_clear_type>(current_test))
590		{
591		case CLEAR_BUFFERFV:
592		case CLEAR_PLAIN:
593		{
594			buffer		 = buffer_char;
595			fbo_id		 = m_fbo_char_id;
596			pixel_size   = N_TEXTURE_COMPONENTS;
597			slice_1_data = slice_1_data_char;
598			slice_2_data = slice_2_data_char;
599			slice_3_data = slice_3_data_char;
600			slice_4_data = slice_4_data_char;
601			to_format	= GL_RGBA;
602			to_id		 = m_to_rgba8_id;
603			to_type		 = GL_UNSIGNED_BYTE;
604
605			break;
606		}
607
608		case CLEAR_BUFFERIV:
609		{
610			buffer		 = (void*)buffer_int;
611			fbo_id		 = m_fbo_int_id;
612			pixel_size   = N_TEXTURE_COMPONENTS * sizeof(int);
613			slice_1_data = slice_1_data_int;
614			slice_2_data = slice_2_data_int;
615			slice_3_data = slice_3_data_int;
616			slice_4_data = slice_4_data_int;
617			to_format	= GL_RGBA_INTEGER;
618			to_id		 = m_to_rgba32i_id;
619			to_type		 = GL_INT;
620
621			break;
622		}
623
624		case CLEAR_BUFFERUIV:
625		{
626			buffer		 = (void*)buffer_uint;
627			fbo_id		 = m_fbo_uint_id;
628			pixel_size   = N_TEXTURE_COMPONENTS * sizeof(unsigned int);
629			slice_1_data = slice_1_data_uint;
630			slice_2_data = slice_2_data_uint;
631			slice_3_data = slice_3_data_uint;
632			slice_4_data = slice_4_data_uint;
633			to_format	= GL_RGBA_INTEGER;
634			to_id		 = m_to_rgba32ui_id;
635			to_type		 = GL_UNSIGNED_INT;
636
637			break;
638		}
639
640		default:
641		{
642			/* This location should never be reached */
643			TCU_FAIL("Execution flow failure");
644		}
645		} /* switch (current_test)*/
646
647		/* Restore layer data just in case */
648		gl.bindTexture(GL_TEXTURE_3D, to_id);
649		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
650						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_1_data);
651		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
652						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_2_data);
653		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
654						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_3_data);
655		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
656						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_4_data);
657
658		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed.");
659
660		/* Issue requested clear call */
661		gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
662
663		switch (current_test)
664		{
665		case CLEAR_PLAIN:
666		{
667			gl.clearColor(clear_color_float[0], clear_color_float[1], clear_color_float[2], clear_color_float[3]);
668			gl.clear(GL_COLOR_BUFFER_BIT);
669
670			break;
671		}
672
673		case CLEAR_BUFFERIV:
674		{
675			gl.clearBufferiv(GL_COLOR, 0 /* draw buffer index */, clear_color_int);
676
677			break;
678		}
679
680		case CLEAR_BUFFERUIV:
681		{
682			gl.clearBufferuiv(GL_COLOR, 0 /* draw buffer index */, (const glw::GLuint*)clear_color_int);
683
684			break;
685		}
686
687		case CLEAR_BUFFERFV:
688		{
689			gl.clearBufferfv(GL_COLOR, 0 /* draw buffer index */, clear_color_float);
690
691			break;
692		}
693
694		default:
695		{
696			/* This location should never be reached */
697			TCU_FAIL("Execution flow failure");
698		}
699		} /* switch (current_test) */
700
701		/* Make sure no error was generated */
702		GLU_EXPECT_NO_ERROR(gl.getError(), "Clear call failed.");
703
704		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
705		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create read framebuffer object!");
706
707		/* Check the layer data after a clear call */
708		for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer)
709		{
710			gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */, n_layer);
711			gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, to_format, to_type, buffer);
712
713			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
714
715			/* If we requested an integer clear, the pixels we obtained should be reset to specific values.
716			 * If we asked for a FP-based clear, consider an epsilon. */
717			for (y = 0; y < TEXTURE_HEIGHT; ++y)
718			{
719				const int	  row_size = TEXTURE_WIDTH * pixel_size;
720				unsigned char* row		= (unsigned char*)buffer + y * row_size;
721
722				for (x = 0; x < TEXTURE_WIDTH; ++x)
723				{
724					if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV)
725					{
726						unsigned int* pixel = (unsigned int*)(row + x * pixel_size);
727						if (memcmp(pixel, clear_color_int, sizeof(clear_color_int)) != 0)
728						{
729							/* Test fails at this point */
730							m_testCtx.getLog()
731								<< tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
732								<< clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2]
733								<< ", " << clear_color_int[3] << "] is different from the one retrieved ["
734								<< (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
735								<< (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
736
737							TCU_FAIL("Data comparison failure");
738						} /* if (memcmp(pixel, clear_color_int, sizeof(clear_color_int) ) != 0) */
739					}	 /* if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) */
740					else
741					{
742#define EPSILON (1)
743
744						unsigned char* pixel = (unsigned char*)(row + x * pixel_size);
745
746						if (de::abs((int)pixel[0] - clear_color_int[0]) > EPSILON ||
747							de::abs((int)pixel[1] - clear_color_int[1]) > EPSILON ||
748							de::abs((int)pixel[2] - clear_color_int[2]) > EPSILON ||
749							de::abs((int)pixel[3] - clear_color_int[3]) > EPSILON)
750						{
751							/* Test fails at this point */
752							m_testCtx.getLog()
753								<< tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
754								<< clear_color_int[0] << ", " << clear_color_int[1] << ", " << clear_color_int[2]
755								<< ", " << clear_color_int[3] << "] is different from the one retrieved ["
756								<< (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
757								<< (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
758
759							TCU_FAIL("Data comparison failure");
760						} /* if (pixel component has exceeded an allowed epsilon) */
761
762#undef EPSILON
763					}
764				} /* for (all pixels) */
765			}	 /* for (all rows) */
766		}		  /* for (all layers) */
767	}			  /* for (all clear call types) */
768
769	/* Done */
770	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
771	return STOP;
772
773#undef TEXTURE_DEPTH
774#undef TEXTURE_HEIGHT
775#undef TEXTURE_WIDTH
776}
777
778/** Deinitializes GLES objects created during the test. */
779void GeometryShaderLayeredFramebufferClear::deinit(void)
780{
781	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
782
783	if (m_fbo_char_id != 0)
784	{
785		gl.deleteFramebuffers(1, &m_fbo_char_id);
786	}
787
788	if (m_fbo_int_id != 0)
789	{
790		gl.deleteFramebuffers(1, &m_fbo_int_id);
791	}
792
793	if (m_fbo_uint_id != 0)
794	{
795		gl.deleteFramebuffers(1, &m_fbo_uint_id);
796	}
797
798	if (m_to_rgba32i_id != 0)
799	{
800		gl.deleteTextures(1, &m_to_rgba32i_id);
801	}
802
803	if (m_to_rgba32ui_id != 0)
804	{
805		gl.deleteTextures(1, &m_to_rgba32ui_id);
806	}
807
808	if (m_to_rgba8_id != 0)
809	{
810		gl.deleteTextures(1, &m_to_rgba8_id);
811	}
812
813	if (m_read_fbo_id != 0)
814	{
815		gl.deleteFramebuffers(1, &m_read_fbo_id);
816	}
817
818	/* Release base class */
819	TestCaseBase::deinit();
820}
821
822/** Constructor
823 *
824 * @param context       Test context
825 * @param name          Test case's name
826 * @param description   Test case's desricption
827 **/
828GeometryShaderLayeredFramebufferDepth::GeometryShaderLayeredFramebufferDepth(Context&			  context,
829																			 const ExtParameters& extParams,
830																			 const char* name, const char* description)
831	: TestCaseBase(context, extParams, name, description)
832	, m_fbo_id(0)
833	, m_fs_id(0)
834	, m_gs_id(0)
835	, m_po_id(0)
836	, m_read_fbo_id(0)
837	, m_to_a_id(0)
838	, m_to_b_id(0)
839	, m_vao_id(0)
840	, m_vs_id(0)
841{
842	/* Left blank on purpose */
843}
844
845/** Deinitializes GLES objects created during the test. */
846void GeometryShaderLayeredFramebufferDepth::deinit(void)
847{
848	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
849
850	/* Clean up */
851	if (m_fbo_id != 0)
852	{
853		gl.deleteFramebuffers(1, &m_fbo_id);
854	}
855
856	if (m_fs_id != 0)
857	{
858		gl.deleteShader(m_fs_id);
859	}
860
861	if (m_gs_id != 0)
862	{
863		gl.deleteShader(m_gs_id);
864	}
865
866	if (m_po_id != 0)
867	{
868		gl.deleteProgram(m_po_id);
869	}
870
871	if (m_read_fbo_id != 0)
872	{
873		gl.deleteFramebuffers(1, &m_read_fbo_id);
874	}
875
876	if (m_to_a_id != 0)
877	{
878		gl.deleteTextures(1, &m_to_a_id);
879	}
880
881	if (m_to_b_id != 0)
882	{
883		gl.deleteTextures(1, &m_to_b_id);
884	}
885
886	if (m_vao_id != 0)
887	{
888		gl.deleteVertexArrays(1, &m_vao_id);
889	}
890
891	if (m_vs_id != 0)
892	{
893		gl.deleteShader(m_vs_id);
894	}
895
896	/* Release base class */
897	TestCaseBase::deinit();
898}
899
900/** Executes the test.
901 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
902 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
903 *  Note the function throws exception should an error occur!
904 **/
905tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferDepth::iterate(void)
906{
907	/* General variables */
908	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
909	unsigned int		  n  = 0;
910	unsigned int		  x  = 0;
911	unsigned int		  y  = 0;
912
913/* Test-wide definitions */
914#define N_TEXTURE_COMPONENTS (4)
915#define TEXTURE_DEPTH (4)
916#define TEXTURE_HEIGHT (4)
917#define TEXTURE_WIDTH (4)
918
919	/* Fragment shader code */
920	const char* fs_code = "${VERSION}\n"
921						  "\n"
922						  "precision highp float;\n"
923						  "\n"
924						  "out vec4 result;\n"
925						  "\n"
926						  "void main()\n"
927						  "{\n"
928						  "    result = vec4(1.0);\n"
929						  "}\n";
930
931	const char* gs_code = "${VERSION}\n"
932						  "${GEOMETRY_SHADER_REQUIRE}\n"
933						  "\n"
934						  "layout(points)                          in;\n"
935						  "layout(triangle_strip, max_vertices=64) out;\n"
936						  "\n"
937						  "void main()\n"
938						  "{\n"
939						  "    for (int n = 0; n < 4; ++n)\n"
940						  "    {\n"
941						  "        float depth = -1.0 + float(n) * 0.5;\n"
942						  "\n"
943						  "        gl_Layer    = n;\n"
944						  "        gl_Position = vec4(1, 1, depth, 1);\n"
945						  "        EmitVertex();\n"
946						  "\n"
947						  "        gl_Layer    = n;\n"
948						  "        gl_Position = vec4(1, -1, depth, 1);\n"
949						  "        EmitVertex();\n"
950						  "\n"
951						  "        gl_Layer    = n;\n"
952						  "        gl_Position = vec4(-1, 1, depth, 1);\n"
953						  "        EmitVertex();\n"
954						  "\n"
955						  "        gl_Layer    = n;\n"
956						  "        gl_Position = vec4(-1, -1, depth, 1);\n"
957						  "        EmitVertex();\n"
958						  "\n"
959						  "        EndPrimitive();\n"
960						  "    }\n"
961						  "}\n";
962
963	/* This test should only run if EXT_geometry_shader is supported */
964	if (!m_is_geometry_shader_extension_supported)
965	{
966		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
967	}
968
969	/* Set up texture objects we will be using for the test */
970	gl.genTextures(1, &m_to_a_id);
971	gl.genTextures(1, &m_to_b_id);
972
973	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
974	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
975	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
976	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT,
977					TEXTURE_DEPTH);
978
979	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture objects");
980
981	/* Set up framebuffer object we will use for the test */
982	gl.genFramebuffers(1, &m_fbo_id);
983	gl.genFramebuffers(1, &m_read_fbo_id);
984
985	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
986
987	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
988	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_to_b_id, 0 /* level */);
989
990	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object");
991
992	if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
993	{
994		m_testCtx.getLog() << tcu::TestLog::Message
995						   << "Draw framebuffer is incomplete: " << gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER)
996						   << tcu::TestLog::EndMessage;
997
998		TCU_FAIL("Draw framebuffer is incomplete.");
999	}
1000
1001	/* Set up shader objects */
1002	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1003	m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1004	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1005
1006	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize shader objects");
1007
1008	/* Set up program object */
1009	m_po_id = gl.createProgram();
1010
1011	if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */,
1012					  &m_boilerplate_vs_code))
1013	{
1014		TCU_FAIL("Could not build program object");
1015	}
1016
1017	/* Set up vertex array object */
1018	gl.genVertexArrays(1, &m_vao_id);
1019	gl.bindVertexArray(m_vao_id);
1020
1021	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind vertex array object");
1022
1023	/* Clear the depth attachment before we continue */
1024	gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */);
1025	gl.clearDepthf(0.5f);
1026	gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1027
1028	GLU_EXPECT_NO_ERROR(gl.getError(), "Depth buffer clear operation failed");
1029
1030	/* Render */
1031	gl.useProgram(m_po_id);
1032	gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
1033
1034	gl.enable(GL_DEPTH_TEST);
1035	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1036
1037	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
1038
1039	/* Verify the output */
1040	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
1041
1042	for (n = 0; n < TEXTURE_DEPTH; ++n)
1043	{
1044		unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
1045		unsigned char ref_color[4];
1046
1047		/* Determine reference color */
1048		if (n < 2)
1049		{
1050			memset(ref_color, 0xFF, sizeof(ref_color));
1051		}
1052		else
1053		{
1054			memset(ref_color, 0, sizeof(ref_color));
1055		}
1056
1057		/* Read the rendered layer data */
1058		gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
1059		gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
1060
1061		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
1062
1063		/* Compare all pixels against the reference value */
1064		for (y = 0; y < TEXTURE_HEIGHT; ++y)
1065		{
1066			const unsigned int   pixel_size = N_TEXTURE_COMPONENTS;
1067			const unsigned int   row_width  = TEXTURE_WIDTH * pixel_size;
1068			const unsigned char* row_data   = buffer + y * row_width;
1069
1070			for (x = 0; x < TEXTURE_WIDTH; ++x)
1071			{
1072				const unsigned char* result = row_data + x * pixel_size;
1073
1074				if (memcmp(result, ref_color, sizeof(ref_color)) != 0)
1075				{
1076					m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") "
1077									   << "Reference value is different than the rendered data: "
1078									   << "(" << (unsigned int)ref_color[0] << ", " << (unsigned int)ref_color[1]
1079									   << ", " << (unsigned int)ref_color[2] << ", " << (unsigned int)ref_color[3]
1080									   << ") vs "
1081									   << "(" << (unsigned int)result[0] << ", " << (unsigned int)result[1] << ", "
1082									   << (unsigned int)result[2] << ", " << (unsigned int)result[3] << ")."
1083									   << tcu::TestLog::EndMessage;
1084
1085					TCU_FAIL("Rendered data mismatch");
1086				} /* if (memcmp(row_data + x * pixel_size, ref_color, sizeof(ref_color) ) != 0)*/
1087			}	 /* for (all pixels in a row) */
1088		}		  /* for (all rows) */
1089	}			  /* for (all layers) */
1090
1091	/* Done */
1092	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1093	return STOP;
1094
1095#undef N_TEXTURE_COMPONENTS
1096#undef TEXTURE_DEPTH
1097#undef TEXTURE_HEIGHT
1098#undef TEXTURE_WIDTH
1099}
1100
1101/** Constructor
1102 *
1103 * @param context       Test context
1104 * @param name          Test case's name
1105 * @param description   Test case's desricption
1106 **/
1107GeometryShaderLayeredFramebufferStencil::GeometryShaderLayeredFramebufferStencil(Context&			  context,
1108																				 const ExtParameters& extParams,
1109																				 const char*		  name,
1110																				 const char*		  description)
1111	: TestCaseBase(context, extParams, name, description)
1112	, m_fbo_id(0)
1113	, m_fs_id(0)
1114	, m_gs_id(0)
1115	, m_po_id(0)
1116	, m_to_a_id(0)
1117	, m_to_b_id(0)
1118	, m_vao_id(0)
1119	, m_vs_id(0)
1120{
1121	/* Left blank on purpose */
1122}
1123
1124/** Deinitializes GLES objects created during the test. */
1125void GeometryShaderLayeredFramebufferStencil::deinit(void)
1126{
1127	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1128
1129	/* Clean up */
1130	if (m_fbo_id != 0)
1131	{
1132		gl.deleteFramebuffers(1, &m_fbo_id);
1133	}
1134
1135	if (m_fs_id != 0)
1136	{
1137		gl.deleteShader(m_fs_id);
1138	}
1139
1140	if (m_gs_id != 0)
1141	{
1142		gl.deleteShader(m_gs_id);
1143	}
1144
1145	if (m_po_id != 0)
1146	{
1147		gl.deleteProgram(m_po_id);
1148	}
1149
1150	if (m_to_a_id != 0)
1151	{
1152		gl.deleteTextures(1, &m_to_a_id);
1153	}
1154
1155	if (m_to_b_id != 0)
1156	{
1157		gl.deleteTextures(1, &m_to_b_id);
1158	}
1159
1160	if (m_vao_id != 0)
1161	{
1162		gl.deleteVertexArrays(1, &m_vao_id);
1163	}
1164
1165	if (m_vs_id != 0)
1166	{
1167		gl.deleteShader(m_vs_id);
1168	}
1169
1170	/* Release base class */
1171	TestCaseBase::deinit();
1172}
1173
1174/** Executes the test.
1175 *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1176 *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1177 *  Note the function throws exception should an error occur!
1178 **/
1179tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferStencil::iterate(void)
1180{
1181	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1182
1183/* Test-wide definitions */
1184#define N_TEXTURE_COMPONENTS (4)
1185#define TEXTURE_DEPTH (4)
1186#define TEXTURE_HEIGHT (4)
1187#define TEXTURE_WIDTH (8)
1188
1189	/* Fragment shader code */
1190	const char* fs_code = "${VERSION}\n"
1191						  "\n"
1192						  "precision highp float;\n"
1193						  "\n"
1194						  "out vec4 result;\n"
1195						  "\n"
1196						  "void main()\n"
1197						  "{\n"
1198						  "    result = vec4(1, 1, 1, 1);\n"
1199						  "}\n";
1200
1201	/* Geometry shader code */
1202	const char* gs_code = "${VERSION}\n"
1203						  "${GEOMETRY_SHADER_REQUIRE}\n"
1204						  "\n"
1205						  "precision highp float;\n"
1206						  "\n"
1207						  "layout (points)                            in;\n"
1208						  "layout (triangle_strip, max_vertices = 16) out;\n"
1209						  "\n"
1210						  "void main()\n"
1211						  "{\n"
1212						  "    for (int n = 0; n < 4; ++n)\n"
1213						  "    {\n"
1214						  "        gl_Position = vec4(1, -1, 0, 1);\n"
1215						  "        gl_Layer    = n;\n"
1216						  "        EmitVertex();\n"
1217						  "\n"
1218						  "        gl_Position = vec4(1,  1, 0, 1);\n"
1219						  "        gl_Layer    = n;\n"
1220						  "        EmitVertex();\n"
1221						  "\n"
1222						  "        gl_Position = vec4(-1, -1, 0, 1);\n"
1223						  "        gl_Layer    = n;\n"
1224						  "        EmitVertex();\n"
1225						  "\n"
1226						  "        gl_Position = vec4(-1,  1, 0, 1);\n"
1227						  "        gl_Layer    = n;\n"
1228						  "        EmitVertex();\n"
1229						  "\n"
1230						  "        EndPrimitive();\n"
1231						  "    }\n"
1232						  "\n"
1233						  "}\n";
1234
1235	/* General variables */
1236	int n = 0;
1237
1238	unsigned char slice_null_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 1 /* byte  per texel */] = { 0 };
1239	unsigned char slice_1_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
1240	unsigned char slice_2_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
1241	unsigned char slice_3_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
1242	unsigned char slice_4_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
1243
1244	/* This test should only run if EXT_geometry_shader is supported */
1245	if (!m_is_geometry_shader_extension_supported)
1246	{
1247		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1248	}
1249
1250	/* Create shader & program objects */
1251	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1252	m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1253	m_po_id = gl.createProgram();
1254	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1255
1256	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader or program objects");
1257
1258	/* Build test program object */
1259	if (!buildProgram(m_po_id, m_fs_id, 1 /* parts */, &fs_code, m_gs_id, 1 /* parts */, &gs_code, m_vs_id,
1260					  1 /* parts */, &m_boilerplate_vs_code))
1261	{
1262		TCU_FAIL("Could not build test program object");
1263	}
1264
1265	/* Generate and bind a vertex array object */
1266	gl.genVertexArrays(1, &m_vao_id);
1267	gl.bindVertexArray(m_vao_id);
1268
1269	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create & bind a vertex array object.");
1270
1271	/* Configure slice data */
1272	for (n = 0; n < TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */; ++n)
1273	{
1274		/* We are okay with depth data being filled with glitch, but need the stencil data to be
1275		 * as per test spec. To keep code simple, we do not differentiate between floating-point and
1276		 * stencil part.
1277		 */
1278		slice_1_data[n] = 2;
1279		slice_2_data[n] = 1;
1280
1281		/* Slices 3 and 4 should be filled with 0s */
1282		slice_3_data[n] = 0;
1283		slice_4_data[n] = 0;
1284	} /* for (all pixels making up slices) */
1285
1286	/* Set up texture objects */
1287	gl.genTextures(1, &m_to_a_id);
1288	gl.genTextures(1, &m_to_b_id);
1289
1290	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
1291	gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH,
1292				  0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1293
1294	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
1295					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1296	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */,
1297					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1298	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */,
1299					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1300	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
1301					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
1302
1303	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object A.");
1304
1305	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
1306	gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_DEPTH32F_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
1307				  TEXTURE_DEPTH, 0 /* border */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);
1308
1309	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
1310					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1311					 slice_1_data);
1312	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */,
1313					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1314					 slice_2_data);
1315	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */,
1316					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1317					 slice_3_data);
1318	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
1319					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
1320					 slice_4_data);
1321
1322	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object B.");
1323
1324	/* Set up depth tests */
1325	gl.disable(GL_DEPTH_TEST);
1326
1327	/* Set up stencil tests */
1328	gl.enable(GL_STENCIL_TEST);
1329	gl.stencilFunc(GL_LESS, 0, /* reference value */ 0xFFFFFFFF /* mask */);
1330
1331	/* Set up framebuffer objects */
1332	gl.genFramebuffers(1, &m_fbo_id);
1333	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
1334
1335	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
1336	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_to_b_id, 0 /* level */);
1337
1338	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer.");
1339
1340	/* Issue the draw call. */
1341	gl.useProgram(m_po_id);
1342	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
1343
1344	GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed.");
1345
1346	/* Check the results */
1347	for (n = 0; n < 4 /* layers */; ++n)
1348	{
1349		glw::GLenum   fbo_completeness													 = GL_NONE;
1350		int			  m																	 = 0;
1351		unsigned char ref_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]	= { 0 };
1352		unsigned char result_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = { 0 };
1353		int			  x																	 = 0;
1354		int			  y																	 = 0;
1355
1356		/* Configure the read framebuffer */
1357		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
1358
1359		gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
1360		gl.framebufferTexture(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0 /* texture */, 0 /* level */);
1361
1362		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer.");
1363
1364		/* Verify read framebuffer is considered complete */
1365		fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
1366
1367		if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE)
1368		{
1369			m_testCtx.getLog() << tcu::TestLog::Message << "Read FBO is incomplete: "
1370							   << "[" << fbo_completeness << "]" << tcu::TestLog::EndMessage;
1371
1372			TCU_FAIL("Read FBO is incomplete.");
1373		}
1374
1375		/* Build reference data */
1376		for (m = 0; m < TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS; ++m)
1377		{
1378			if (n < 2)
1379			{
1380				ref_data[m] = 255;
1381			}
1382			else
1383			{
1384				ref_data[m] = 0;
1385			}
1386		} /* for (all reference pixels) */
1387
1388		/* Read the rendered data */
1389		gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_data);
1390
1391		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed");
1392
1393		for (y = 0; y < TEXTURE_HEIGHT; ++y)
1394		{
1395			int			   pixel_size = N_TEXTURE_COMPONENTS;
1396			int			   row_size   = pixel_size * TEXTURE_WIDTH;
1397			unsigned char* ref_row	= ref_data + y * row_size;
1398			unsigned char* result_row = result_data + y * row_size;
1399
1400			for (x = 0; x < TEXTURE_WIDTH; ++x)
1401			{
1402				if (memcmp(ref_row, result_row, pixel_size) != 0)
1403				{
1404					m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << "): Rendered data "
1405									   << "(" << result_row[0] << ", " << result_row[1] << ", " << result_row[2] << ", "
1406									   << result_row[3] << ")"
1407									   << " is different from reference data "
1408									   << "(" << ref_row[0] << ", " << ref_row[1] << ", " << ref_row[2] << ", "
1409									   << ref_row[3] << ")" << tcu::TestLog::EndMessage;
1410
1411					TCU_FAIL("Data comparison failed");
1412				} /* if (memcmp(ref_row, result_row, pixel_size) != 0) */
1413
1414				ref_row += pixel_size;
1415				result_row += pixel_size;
1416			} /* for (all pixels in a row) */
1417		}	 /* for (all pixels) */
1418	}		  /* for (all layers) */
1419
1420	/* Done */
1421	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1422	return STOP;
1423
1424#undef N_TEXTURE_COMPONENTS
1425#undef TEXTURE_DEPTH
1426#undef TEXTURE_HEIGHT
1427#undef TEXTURE_WIDTH
1428}
1429
1430} // namespace glcts
1431