Home | History | Annotate | Download | only in geometry_shader
      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 
     33 namespace 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  **/
     41 GeometryShaderLayeredFramebufferBlending::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. */
     59 void 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  **/
    113 tcu::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  **/
    382 GeometryShaderLayeredFramebufferClear::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  **/
    402 tcu::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 unsigned char clear_color_byte[]  = { 64, 128, 255, 32 };
    578 		const float			clear_color_float[] = { 0.25f, 0.5f, 1.0f, 32.0f / 255.0f };
    579 		const int			clear_color_int[]   = { 64, 128, 255, 32 };
    580 		glw::GLuint			fbo_id				= 0;
    581 		int					pixel_size			= 0;
    582 		void*				slice_1_data		= NULL;
    583 		void*				slice_2_data		= NULL;
    584 		void*				slice_3_data		= NULL;
    585 		void*				slice_4_data		= NULL;
    586 		glw::GLenum			to_format			= GL_NONE;
    587 		glw::GLuint			to_id				= 0;
    588 		glw::GLenum			to_type				= GL_NONE;
    589 
    590 		switch (static_cast<_clear_type>(current_test))
    591 		{
    592 		case CLEAR_BUFFERFV:
    593 		case CLEAR_PLAIN:
    594 		{
    595 			buffer		 = buffer_char;
    596 			fbo_id		 = m_fbo_char_id;
    597 			pixel_size   = N_TEXTURE_COMPONENTS;
    598 			slice_1_data = slice_1_data_char;
    599 			slice_2_data = slice_2_data_char;
    600 			slice_3_data = slice_3_data_char;
    601 			slice_4_data = slice_4_data_char;
    602 			to_format	= GL_RGBA;
    603 			to_id		 = m_to_rgba8_id;
    604 			to_type		 = GL_UNSIGNED_BYTE;
    605 
    606 			break;
    607 		}
    608 
    609 		case CLEAR_BUFFERIV:
    610 		{
    611 			buffer		 = (void*)buffer_int;
    612 			fbo_id		 = m_fbo_int_id;
    613 			pixel_size   = N_TEXTURE_COMPONENTS * sizeof(int);
    614 			slice_1_data = slice_1_data_int;
    615 			slice_2_data = slice_2_data_int;
    616 			slice_3_data = slice_3_data_int;
    617 			slice_4_data = slice_4_data_int;
    618 			to_format	= GL_RGBA_INTEGER;
    619 			to_id		 = m_to_rgba32i_id;
    620 			to_type		 = GL_INT;
    621 
    622 			break;
    623 		}
    624 
    625 		case CLEAR_BUFFERUIV:
    626 		{
    627 			buffer		 = (void*)buffer_uint;
    628 			fbo_id		 = m_fbo_uint_id;
    629 			pixel_size   = N_TEXTURE_COMPONENTS * sizeof(unsigned int);
    630 			slice_1_data = slice_1_data_uint;
    631 			slice_2_data = slice_2_data_uint;
    632 			slice_3_data = slice_3_data_uint;
    633 			slice_4_data = slice_4_data_uint;
    634 			to_format	= GL_RGBA_INTEGER;
    635 			to_id		 = m_to_rgba32ui_id;
    636 			to_type		 = GL_UNSIGNED_INT;
    637 
    638 			break;
    639 		}
    640 
    641 		default:
    642 		{
    643 			/* This location should never be reached */
    644 			TCU_FAIL("Execution flow failure");
    645 		}
    646 		} /* switch (current_test)*/
    647 
    648 		/* Restore layer data just in case */
    649 		gl.bindTexture(GL_TEXTURE_3D, to_id);
    650 		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */, TEXTURE_WIDTH,
    651 						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_1_data);
    652 		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */, TEXTURE_WIDTH,
    653 						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_2_data);
    654 		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */, TEXTURE_WIDTH,
    655 						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_3_data);
    656 		gl.texSubImage3D(GL_TEXTURE_3D, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */, TEXTURE_WIDTH,
    657 						 TEXTURE_HEIGHT, 1 /* depth */, to_format, to_type, slice_4_data);
    658 
    659 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed.");
    660 
    661 		/* Issue requested clear call */
    662 		gl.bindFramebuffer(GL_FRAMEBUFFER, fbo_id);
    663 
    664 		switch (current_test)
    665 		{
    666 		case CLEAR_PLAIN:
    667 		{
    668 			gl.clearColor(clear_color_float[0], clear_color_float[1], clear_color_float[2], clear_color_float[3]);
    669 			gl.clear(GL_COLOR_BUFFER_BIT);
    670 
    671 			break;
    672 		}
    673 
    674 		case CLEAR_BUFFERIV:
    675 		{
    676 			gl.clearBufferiv(GL_COLOR, 0 /* draw buffer index */, clear_color_int);
    677 
    678 			break;
    679 		}
    680 
    681 		case CLEAR_BUFFERUIV:
    682 		{
    683 			gl.clearBufferuiv(GL_COLOR, 0 /* draw buffer index */, (const glw::GLuint*)clear_color_int);
    684 
    685 			break;
    686 		}
    687 
    688 		case CLEAR_BUFFERFV:
    689 		{
    690 			gl.clearBufferfv(GL_COLOR, 0 /* draw buffer index */, clear_color_float);
    691 
    692 			break;
    693 		}
    694 
    695 		default:
    696 		{
    697 			/* This location should never be reached */
    698 			TCU_FAIL("Execution flow failure");
    699 		}
    700 		} /* switch (current_test) */
    701 
    702 		/* Make sure no error was generated */
    703 		GLU_EXPECT_NO_ERROR(gl.getError(), "Clear call failed.");
    704 
    705 		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
    706 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create read framebuffer object!");
    707 
    708 		/* Check the layer data after a clear call */
    709 		for (n_layer = 0; n_layer < TEXTURE_DEPTH; ++n_layer)
    710 		{
    711 			gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, to_id, 0 /* level */, n_layer);
    712 			gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, to_format, to_type, buffer);
    713 
    714 			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
    715 
    716 			/* If we requested an integer clear, the pixels we obtained should be reset to specific values.
    717 			 * If we asked for a FP-based clear, consider an epsilon. */
    718 			for (y = 0; y < TEXTURE_HEIGHT; ++y)
    719 			{
    720 				const int	  row_size = TEXTURE_WIDTH * pixel_size;
    721 				unsigned char* row		= (unsigned char*)buffer + y * row_size;
    722 
    723 				for (x = 0; x < TEXTURE_WIDTH; ++x)
    724 				{
    725 					if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV)
    726 					{
    727 						unsigned int* pixel = (unsigned int*)(row + x * pixel_size);
    728 
    729 						if (memcmp(pixel, clear_color_int, sizeof(clear_color_int)) != 0)
    730 						{
    731 							/* Test fails at this point */
    732 							m_testCtx.getLog()
    733 								<< tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
    734 								<< clear_color_byte[0] << ", " << clear_color_byte[1] << ", " << clear_color_byte[2]
    735 								<< ", " << clear_color_byte[3] << "] is different from the one retrieved ["
    736 								<< (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
    737 								<< (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
    738 
    739 							TCU_FAIL("Data comparison failure");
    740 						} /* if (memcmp(pixel, clear_color_byte, sizeof(clear_color_byte) ) != 0) */
    741 					}	 /* if (current_test == CLEAR_BUFFERIV || current_test == CLEAR_BUFFERUIV) */
    742 					else
    743 					{
    744 #define EPSILON (1)
    745 
    746 						unsigned char* pixel = (unsigned char*)(row + x * pixel_size);
    747 
    748 						if (de::abs((int)pixel[0] - clear_color_int[0]) > EPSILON ||
    749 							de::abs((int)pixel[1] - clear_color_int[1]) > EPSILON ||
    750 							de::abs((int)pixel[2] - clear_color_int[2]) > EPSILON ||
    751 							de::abs((int)pixel[3] - clear_color_int[3]) > EPSILON)
    752 						{
    753 							/* Test fails at this point */
    754 							m_testCtx.getLog()
    755 								<< tcu::TestLog::Message << "(x=" << x << " y=" << y << ") Reference pixel ["
    756 								<< clear_color_byte[0] << ", " << clear_color_byte[1] << ", " << clear_color_byte[2]
    757 								<< ", " << clear_color_byte[3] << "] is different from the one retrieved ["
    758 								<< (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", "
    759 								<< (int)pixel[3] << "]" << tcu::TestLog::EndMessage;
    760 
    761 							TCU_FAIL("Data comparison failure");
    762 						} /* if (pixel component has exceeded an allowed epsilon) */
    763 
    764 #undef EPSILON
    765 					}
    766 				} /* for (all pixels) */
    767 			}	 /* for (all rows) */
    768 		}		  /* for (all layers) */
    769 	}			  /* for (all clear call types) */
    770 
    771 	/* Done */
    772 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    773 	return STOP;
    774 
    775 #undef TEXTURE_DEPTH
    776 #undef TEXTURE_HEIGHT
    777 #undef TEXTURE_WIDTH
    778 }
    779 
    780 /** Deinitializes GLES objects created during the test. */
    781 void GeometryShaderLayeredFramebufferClear::deinit(void)
    782 {
    783 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    784 
    785 	if (m_fbo_char_id != 0)
    786 	{
    787 		gl.deleteFramebuffers(1, &m_fbo_char_id);
    788 	}
    789 
    790 	if (m_fbo_int_id != 0)
    791 	{
    792 		gl.deleteFramebuffers(1, &m_fbo_int_id);
    793 	}
    794 
    795 	if (m_fbo_uint_id != 0)
    796 	{
    797 		gl.deleteFramebuffers(1, &m_fbo_uint_id);
    798 	}
    799 
    800 	if (m_to_rgba32i_id != 0)
    801 	{
    802 		gl.deleteTextures(1, &m_to_rgba32i_id);
    803 	}
    804 
    805 	if (m_to_rgba32ui_id != 0)
    806 	{
    807 		gl.deleteTextures(1, &m_to_rgba32ui_id);
    808 	}
    809 
    810 	if (m_to_rgba8_id != 0)
    811 	{
    812 		gl.deleteTextures(1, &m_to_rgba8_id);
    813 	}
    814 
    815 	if (m_read_fbo_id != 0)
    816 	{
    817 		gl.deleteFramebuffers(1, &m_read_fbo_id);
    818 	}
    819 
    820 	/* Release base class */
    821 	TestCaseBase::deinit();
    822 }
    823 
    824 /** Constructor
    825  *
    826  * @param context       Test context
    827  * @param name          Test case's name
    828  * @param description   Test case's desricption
    829  **/
    830 GeometryShaderLayeredFramebufferDepth::GeometryShaderLayeredFramebufferDepth(Context&			  context,
    831 																			 const ExtParameters& extParams,
    832 																			 const char* name, const char* description)
    833 	: TestCaseBase(context, extParams, name, description)
    834 	, m_fbo_id(0)
    835 	, m_fs_id(0)
    836 	, m_gs_id(0)
    837 	, m_po_id(0)
    838 	, m_read_fbo_id(0)
    839 	, m_to_a_id(0)
    840 	, m_to_b_id(0)
    841 	, m_vao_id(0)
    842 	, m_vs_id(0)
    843 {
    844 	/* Left blank on purpose */
    845 }
    846 
    847 /** Deinitializes GLES objects created during the test. */
    848 void GeometryShaderLayeredFramebufferDepth::deinit(void)
    849 {
    850 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    851 
    852 	/* Clean up */
    853 	if (m_fbo_id != 0)
    854 	{
    855 		gl.deleteFramebuffers(1, &m_fbo_id);
    856 	}
    857 
    858 	if (m_fs_id != 0)
    859 	{
    860 		gl.deleteShader(m_fs_id);
    861 	}
    862 
    863 	if (m_gs_id != 0)
    864 	{
    865 		gl.deleteShader(m_gs_id);
    866 	}
    867 
    868 	if (m_po_id != 0)
    869 	{
    870 		gl.deleteProgram(m_po_id);
    871 	}
    872 
    873 	if (m_read_fbo_id != 0)
    874 	{
    875 		gl.deleteFramebuffers(1, &m_read_fbo_id);
    876 	}
    877 
    878 	if (m_to_a_id != 0)
    879 	{
    880 		gl.deleteTextures(1, &m_to_a_id);
    881 	}
    882 
    883 	if (m_to_b_id != 0)
    884 	{
    885 		gl.deleteTextures(1, &m_to_b_id);
    886 	}
    887 
    888 	if (m_vao_id != 0)
    889 	{
    890 		gl.deleteVertexArrays(1, &m_vao_id);
    891 	}
    892 
    893 	if (m_vs_id != 0)
    894 	{
    895 		gl.deleteShader(m_vs_id);
    896 	}
    897 
    898 	/* Release base class */
    899 	TestCaseBase::deinit();
    900 }
    901 
    902 /** Executes the test.
    903  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
    904  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
    905  *  Note the function throws exception should an error occur!
    906  **/
    907 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferDepth::iterate(void)
    908 {
    909 	/* General variables */
    910 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    911 	unsigned int		  n  = 0;
    912 	unsigned int		  x  = 0;
    913 	unsigned int		  y  = 0;
    914 
    915 /* Test-wide definitions */
    916 #define N_TEXTURE_COMPONENTS (4)
    917 #define TEXTURE_DEPTH (4)
    918 #define TEXTURE_HEIGHT (4)
    919 #define TEXTURE_WIDTH (4)
    920 
    921 	/* Fragment shader code */
    922 	const char* fs_code = "${VERSION}\n"
    923 						  "\n"
    924 						  "precision highp float;\n"
    925 						  "\n"
    926 						  "out vec4 result;\n"
    927 						  "\n"
    928 						  "void main()\n"
    929 						  "{\n"
    930 						  "    result = vec4(1.0);\n"
    931 						  "}\n";
    932 
    933 	const char* gs_code = "${VERSION}\n"
    934 						  "${GEOMETRY_SHADER_REQUIRE}\n"
    935 						  "\n"
    936 						  "layout(points)                          in;\n"
    937 						  "layout(triangle_strip, max_vertices=64) out;\n"
    938 						  "\n"
    939 						  "void main()\n"
    940 						  "{\n"
    941 						  "    for (int n = 0; n < 4; ++n)\n"
    942 						  "    {\n"
    943 						  "        float depth = -1.0 + float(n) * 0.5;\n"
    944 						  "\n"
    945 						  "        gl_Layer    = n;\n"
    946 						  "        gl_Position = vec4(1, 1, depth, 1);\n"
    947 						  "        EmitVertex();\n"
    948 						  "\n"
    949 						  "        gl_Layer    = n;\n"
    950 						  "        gl_Position = vec4(1, -1, depth, 1);\n"
    951 						  "        EmitVertex();\n"
    952 						  "\n"
    953 						  "        gl_Layer    = n;\n"
    954 						  "        gl_Position = vec4(-1, 1, depth, 1);\n"
    955 						  "        EmitVertex();\n"
    956 						  "\n"
    957 						  "        gl_Layer    = n;\n"
    958 						  "        gl_Position = vec4(-1, -1, depth, 1);\n"
    959 						  "        EmitVertex();\n"
    960 						  "\n"
    961 						  "        EndPrimitive();\n"
    962 						  "    }\n"
    963 						  "}\n";
    964 
    965 	/* This test should only run if EXT_geometry_shader is supported */
    966 	if (!m_is_geometry_shader_extension_supported)
    967 	{
    968 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
    969 	}
    970 
    971 	/* Set up texture objects we will be using for the test */
    972 	gl.genTextures(1, &m_to_a_id);
    973 	gl.genTextures(1, &m_to_b_id);
    974 
    975 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
    976 	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
    977 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
    978 	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, GL_DEPTH_COMPONENT32F, TEXTURE_WIDTH, TEXTURE_HEIGHT,
    979 					TEXTURE_DEPTH);
    980 
    981 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture objects");
    982 
    983 	/* Set up framebuffer object we will use for the test */
    984 	gl.genFramebuffers(1, &m_fbo_id);
    985 	gl.genFramebuffers(1, &m_read_fbo_id);
    986 
    987 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
    988 
    989 	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
    990 	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_to_b_id, 0 /* level */);
    991 
    992 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize framebuffer object");
    993 
    994 	if (gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
    995 	{
    996 		m_testCtx.getLog() << tcu::TestLog::Message
    997 						   << "Draw framebuffer is incomplete: " << gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER)
    998 						   << tcu::TestLog::EndMessage;
    999 
   1000 		TCU_FAIL("Draw framebuffer is incomplete.");
   1001 	}
   1002 
   1003 	/* Set up shader objects */
   1004 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   1005 	m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
   1006 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   1007 
   1008 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize shader objects");
   1009 
   1010 	/* Set up program object */
   1011 	m_po_id = gl.createProgram();
   1012 
   1013 	if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id, 1 /* part */,
   1014 					  &m_boilerplate_vs_code))
   1015 	{
   1016 		TCU_FAIL("Could not build program object");
   1017 	}
   1018 
   1019 	/* Set up vertex array object */
   1020 	gl.genVertexArrays(1, &m_vao_id);
   1021 	gl.bindVertexArray(m_vao_id);
   1022 
   1023 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind vertex array object");
   1024 
   1025 	/* Clear the depth attachment before we continue */
   1026 	gl.clearColor(0.0f /* red */, 0.0f /* green */, 0.0f /* blue */, 0.0f /* alpha */);
   1027 	gl.clearDepthf(0.5f);
   1028 	gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   1029 
   1030 	GLU_EXPECT_NO_ERROR(gl.getError(), "Depth buffer clear operation failed");
   1031 
   1032 	/* Render */
   1033 	gl.useProgram(m_po_id);
   1034 	gl.viewport(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT);
   1035 
   1036 	gl.enable(GL_DEPTH_TEST);
   1037 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
   1038 
   1039 	GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed");
   1040 
   1041 	/* Verify the output */
   1042 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_read_fbo_id);
   1043 
   1044 	for (n = 0; n < TEXTURE_DEPTH; ++n)
   1045 	{
   1046 		unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS];
   1047 		unsigned char ref_color[4];
   1048 
   1049 		/* Determine reference color */
   1050 		if (n < 2)
   1051 		{
   1052 			memset(ref_color, 0xFF, sizeof(ref_color));
   1053 		}
   1054 		else
   1055 		{
   1056 			memset(ref_color, 0, sizeof(ref_color));
   1057 		}
   1058 
   1059 		/* Read the rendered layer data */
   1060 		gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
   1061 		gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
   1062 
   1063 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
   1064 
   1065 		/* Compare all pixels against the reference value */
   1066 		for (y = 0; y < TEXTURE_HEIGHT; ++y)
   1067 		{
   1068 			const unsigned int   pixel_size = N_TEXTURE_COMPONENTS;
   1069 			const unsigned int   row_width  = TEXTURE_WIDTH * pixel_size;
   1070 			const unsigned char* row_data   = buffer + y * row_width;
   1071 
   1072 			for (x = 0; x < TEXTURE_WIDTH; ++x)
   1073 			{
   1074 				const unsigned char* result = row_data + x * pixel_size;
   1075 
   1076 				if (memcmp(result, ref_color, sizeof(ref_color)) != 0)
   1077 				{
   1078 					m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << ") "
   1079 									   << "Reference value is different than the rendered data: "
   1080 									   << "(" << (unsigned int)ref_color[0] << ", " << (unsigned int)ref_color[1]
   1081 									   << ", " << (unsigned int)ref_color[2] << ", " << (unsigned int)ref_color[3]
   1082 									   << ") vs "
   1083 									   << "(" << (unsigned int)result[0] << ", " << (unsigned int)result[1] << ", "
   1084 									   << (unsigned int)result[2] << ", " << (unsigned int)result[3] << ")."
   1085 									   << tcu::TestLog::EndMessage;
   1086 
   1087 					TCU_FAIL("Rendered data mismatch");
   1088 				} /* if (memcmp(row_data + x * pixel_size, ref_color, sizeof(ref_color) ) != 0)*/
   1089 			}	 /* for (all pixels in a row) */
   1090 		}		  /* for (all rows) */
   1091 	}			  /* for (all layers) */
   1092 
   1093 	/* Done */
   1094 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1095 	return STOP;
   1096 
   1097 #undef N_TEXTURE_COMPONENTS
   1098 #undef TEXTURE_DEPTH
   1099 #undef TEXTURE_HEIGHT
   1100 #undef TEXTURE_WIDTH
   1101 }
   1102 
   1103 /** Constructor
   1104  *
   1105  * @param context       Test context
   1106  * @param name          Test case's name
   1107  * @param description   Test case's desricption
   1108  **/
   1109 GeometryShaderLayeredFramebufferStencil::GeometryShaderLayeredFramebufferStencil(Context&			  context,
   1110 																				 const ExtParameters& extParams,
   1111 																				 const char*		  name,
   1112 																				 const char*		  description)
   1113 	: TestCaseBase(context, extParams, name, description)
   1114 	, m_fbo_id(0)
   1115 	, m_fs_id(0)
   1116 	, m_gs_id(0)
   1117 	, m_po_id(0)
   1118 	, m_to_a_id(0)
   1119 	, m_to_b_id(0)
   1120 	, m_vao_id(0)
   1121 	, m_vs_id(0)
   1122 {
   1123 	/* Left blank on purpose */
   1124 }
   1125 
   1126 /** Deinitializes GLES objects created during the test. */
   1127 void GeometryShaderLayeredFramebufferStencil::deinit(void)
   1128 {
   1129 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1130 
   1131 	/* Clean up */
   1132 	if (m_fbo_id != 0)
   1133 	{
   1134 		gl.deleteFramebuffers(1, &m_fbo_id);
   1135 	}
   1136 
   1137 	if (m_fs_id != 0)
   1138 	{
   1139 		gl.deleteShader(m_fs_id);
   1140 	}
   1141 
   1142 	if (m_gs_id != 0)
   1143 	{
   1144 		gl.deleteShader(m_gs_id);
   1145 	}
   1146 
   1147 	if (m_po_id != 0)
   1148 	{
   1149 		gl.deleteProgram(m_po_id);
   1150 	}
   1151 
   1152 	if (m_to_a_id != 0)
   1153 	{
   1154 		gl.deleteTextures(1, &m_to_a_id);
   1155 	}
   1156 
   1157 	if (m_to_b_id != 0)
   1158 	{
   1159 		gl.deleteTextures(1, &m_to_b_id);
   1160 	}
   1161 
   1162 	if (m_vao_id != 0)
   1163 	{
   1164 		gl.deleteVertexArrays(1, &m_vao_id);
   1165 	}
   1166 
   1167 	if (m_vs_id != 0)
   1168 	{
   1169 		gl.deleteShader(m_vs_id);
   1170 	}
   1171 
   1172 	/* Release base class */
   1173 	TestCaseBase::deinit();
   1174 }
   1175 
   1176 /** Executes the test.
   1177  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
   1178  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
   1179  *  Note the function throws exception should an error occur!
   1180  **/
   1181 tcu::TestNode::IterateResult GeometryShaderLayeredFramebufferStencil::iterate(void)
   1182 {
   1183 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   1184 
   1185 /* Test-wide definitions */
   1186 #define N_TEXTURE_COMPONENTS (4)
   1187 #define TEXTURE_DEPTH (4)
   1188 #define TEXTURE_HEIGHT (4)
   1189 #define TEXTURE_WIDTH (8)
   1190 
   1191 	/* Fragment shader code */
   1192 	const char* fs_code = "${VERSION}\n"
   1193 						  "\n"
   1194 						  "precision highp float;\n"
   1195 						  "\n"
   1196 						  "out vec4 result;\n"
   1197 						  "\n"
   1198 						  "void main()\n"
   1199 						  "{\n"
   1200 						  "    result = vec4(1, 1, 1, 1);\n"
   1201 						  "}\n";
   1202 
   1203 	/* Geometry shader code */
   1204 	const char* gs_code = "${VERSION}\n"
   1205 						  "${GEOMETRY_SHADER_REQUIRE}\n"
   1206 						  "\n"
   1207 						  "precision highp float;\n"
   1208 						  "\n"
   1209 						  "layout (points)                            in;\n"
   1210 						  "layout (triangle_strip, max_vertices = 16) out;\n"
   1211 						  "\n"
   1212 						  "void main()\n"
   1213 						  "{\n"
   1214 						  "    for (int n = 0; n < 4; ++n)\n"
   1215 						  "    {\n"
   1216 						  "        gl_Position = vec4(1, -1, 0, 1);\n"
   1217 						  "        gl_Layer    = n;\n"
   1218 						  "        EmitVertex();\n"
   1219 						  "\n"
   1220 						  "        gl_Position = vec4(1,  1, 0, 1);\n"
   1221 						  "        gl_Layer    = n;\n"
   1222 						  "        EmitVertex();\n"
   1223 						  "\n"
   1224 						  "        gl_Position = vec4(-1, -1, 0, 1);\n"
   1225 						  "        gl_Layer    = n;\n"
   1226 						  "        EmitVertex();\n"
   1227 						  "\n"
   1228 						  "        gl_Position = vec4(-1,  1, 0, 1);\n"
   1229 						  "        gl_Layer    = n;\n"
   1230 						  "        EmitVertex();\n"
   1231 						  "\n"
   1232 						  "        EndPrimitive();\n"
   1233 						  "    }\n"
   1234 						  "\n"
   1235 						  "}\n";
   1236 
   1237 	/* General variables */
   1238 	int n = 0;
   1239 
   1240 	unsigned char slice_null_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 1 /* byte  per texel */] = { 0 };
   1241 	unsigned char slice_1_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
   1242 	unsigned char slice_2_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
   1243 	unsigned char slice_3_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
   1244 	unsigned char slice_4_data[TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */]	= { 0 };
   1245 
   1246 	/* This test should only run if EXT_geometry_shader is supported */
   1247 	if (!m_is_geometry_shader_extension_supported)
   1248 	{
   1249 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
   1250 	}
   1251 
   1252 	/* Create shader & program objects */
   1253 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   1254 	m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
   1255 	m_po_id = gl.createProgram();
   1256 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   1257 
   1258 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shader or program objects");
   1259 
   1260 	/* Build test program object */
   1261 	if (!buildProgram(m_po_id, m_fs_id, 1 /* parts */, &fs_code, m_gs_id, 1 /* parts */, &gs_code, m_vs_id,
   1262 					  1 /* parts */, &m_boilerplate_vs_code))
   1263 	{
   1264 		TCU_FAIL("Could not build test program object");
   1265 	}
   1266 
   1267 	/* Generate and bind a vertex array object */
   1268 	gl.genVertexArrays(1, &m_vao_id);
   1269 	gl.bindVertexArray(m_vao_id);
   1270 
   1271 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create & bind a vertex array object.");
   1272 
   1273 	/* Configure slice data */
   1274 	for (n = 0; n < TEXTURE_DEPTH * TEXTURE_WIDTH * TEXTURE_HEIGHT * 8 /* bytes per texel */; ++n)
   1275 	{
   1276 		/* We are okay with depth data being filled with glitch, but need the stencil data to be
   1277 		 * as per test spec. To keep code simple, we do not differentiate between floating-point and
   1278 		 * stencil part.
   1279 		 */
   1280 		slice_1_data[n] = 2;
   1281 		slice_2_data[n] = 1;
   1282 
   1283 		/* Slices 3 and 4 should be filled with 0s */
   1284 		slice_3_data[n] = 0;
   1285 		slice_4_data[n] = 0;
   1286 	} /* for (all pixels making up slices) */
   1287 
   1288 	/* Set up texture objects */
   1289 	gl.genTextures(1, &m_to_a_id);
   1290 	gl.genTextures(1, &m_to_b_id);
   1291 
   1292 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_a_id);
   1293 	gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH,
   1294 				  0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
   1295 
   1296 	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* 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 */, 1 /* 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 */, 2 /* zoffset */,
   1301 					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
   1302 	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
   1303 					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_RGBA, GL_UNSIGNED_BYTE, slice_null_data);
   1304 
   1305 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object A.");
   1306 
   1307 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_to_b_id);
   1308 	gl.texImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, GL_DEPTH32F_STENCIL8, TEXTURE_WIDTH, TEXTURE_HEIGHT,
   1309 				  TEXTURE_DEPTH, 0 /* border */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);
   1310 
   1311 	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
   1312 					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
   1313 					 slice_1_data);
   1314 	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 1 /* zoffset */,
   1315 					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
   1316 					 slice_2_data);
   1317 	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 2 /* zoffset */,
   1318 					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
   1319 					 slice_3_data);
   1320 	gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, 0 /* level */, 0 /* xoffset */, 0 /* yoffset */, 3 /* zoffset */,
   1321 					 TEXTURE_WIDTH, TEXTURE_HEIGHT, 1 /* depth */, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
   1322 					 slice_4_data);
   1323 
   1324 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up texture object B.");
   1325 
   1326 	/* Set up depth tests */
   1327 	gl.disable(GL_DEPTH_TEST);
   1328 
   1329 	/* Set up stencil tests */
   1330 	gl.enable(GL_STENCIL_TEST);
   1331 	gl.stencilFunc(GL_LESS, 0, /* reference value */ 0xFFFFFFFF /* mask */);
   1332 
   1333 	/* Set up framebuffer objects */
   1334 	gl.genFramebuffers(1, &m_fbo_id);
   1335 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id);
   1336 
   1337 	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */);
   1338 	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_to_b_id, 0 /* level */);
   1339 
   1340 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up draw framebuffer.");
   1341 
   1342 	/* Issue the draw call. */
   1343 	gl.useProgram(m_po_id);
   1344 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
   1345 
   1346 	GLU_EXPECT_NO_ERROR(gl.getError(), "Draw call failed.");
   1347 
   1348 	/* Check the results */
   1349 	for (n = 0; n < 4 /* layers */; ++n)
   1350 	{
   1351 		glw::GLenum   fbo_completeness													 = GL_NONE;
   1352 		int			  m																	 = 0;
   1353 		unsigned char ref_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS]	= { 0 };
   1354 		unsigned char result_data[TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS] = { 0 };
   1355 		int			  x																	 = 0;
   1356 		int			  y																	 = 0;
   1357 
   1358 		/* Configure the read framebuffer */
   1359 		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
   1360 
   1361 		gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_to_a_id, 0 /* level */, n);
   1362 		gl.framebufferTexture(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0 /* texture */, 0 /* level */);
   1363 
   1364 		GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set up read framebuffer.");
   1365 
   1366 		/* Verify read framebuffer is considered complete */
   1367 		fbo_completeness = gl.checkFramebufferStatus(GL_READ_FRAMEBUFFER);
   1368 
   1369 		if (fbo_completeness != GL_FRAMEBUFFER_COMPLETE)
   1370 		{
   1371 			m_testCtx.getLog() << tcu::TestLog::Message << "Read FBO is incomplete: "
   1372 							   << "[" << fbo_completeness << "]" << tcu::TestLog::EndMessage;
   1373 
   1374 			TCU_FAIL("Read FBO is incomplete.");
   1375 		}
   1376 
   1377 		/* Build reference data */
   1378 		for (m = 0; m < TEXTURE_WIDTH * TEXTURE_HEIGHT * N_TEXTURE_COMPONENTS; ++m)
   1379 		{
   1380 			if (n < 2)
   1381 			{
   1382 				ref_data[m] = 255;
   1383 			}
   1384 			else
   1385 			{
   1386 				ref_data[m] = 0;
   1387 			}
   1388 		} /* for (all reference pixels) */
   1389 
   1390 		/* Read the rendered data */
   1391 		gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, result_data);
   1392 
   1393 		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() failed");
   1394 
   1395 		for (y = 0; y < TEXTURE_HEIGHT; ++y)
   1396 		{
   1397 			int			   pixel_size = N_TEXTURE_COMPONENTS;
   1398 			int			   row_size   = pixel_size * TEXTURE_WIDTH;
   1399 			unsigned char* ref_row	= ref_data + y * row_size;
   1400 			unsigned char* result_row = result_data + y * row_size;
   1401 
   1402 			for (x = 0; x < TEXTURE_WIDTH; ++x)
   1403 			{
   1404 				if (memcmp(ref_row, result_row, pixel_size) != 0)
   1405 				{
   1406 					m_testCtx.getLog() << tcu::TestLog::Message << "(x=" << x << " y=" << y << "): Rendered data "
   1407 									   << "(" << result_row[0] << ", " << result_row[1] << ", " << result_row[2] << ", "
   1408 									   << result_row[3] << ")"
   1409 									   << " is different from reference data "
   1410 									   << "(" << ref_row[0] << ", " << ref_row[1] << ", " << ref_row[2] << ", "
   1411 									   << ref_row[3] << ")" << tcu::TestLog::EndMessage;
   1412 
   1413 					TCU_FAIL("Data comparison failed");
   1414 				} /* if (memcmp(ref_row, result_row, pixel_size) != 0) */
   1415 
   1416 				ref_row += pixel_size;
   1417 				result_row += pixel_size;
   1418 			} /* for (all pixels in a row) */
   1419 		}	 /* for (all pixels) */
   1420 	}		  /* for (all layers) */
   1421 
   1422 	/* Done */
   1423 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1424 	return STOP;
   1425 
   1426 #undef N_TEXTURE_COMPONENTS
   1427 #undef TEXTURE_DEPTH
   1428 #undef TEXTURE_HEIGHT
   1429 #undef TEXTURE_WIDTH
   1430 }
   1431 
   1432 } // namespace glcts
   1433