1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
3e5c31af7Sopenharmony_ci * -----------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2014-2016 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci */ /*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief
22e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "esextcGeometryShaderLayeredRendering.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
27e5c31af7Sopenharmony_ci#include "gluDefs.hpp"
28e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
29e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
30e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include <algorithm>
33e5c31af7Sopenharmony_ci#include <cstring>
34e5c31af7Sopenharmony_ci#include <string>
35e5c31af7Sopenharmony_ci#include <vector>
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_cinamespace glcts
38e5c31af7Sopenharmony_ci{
39e5c31af7Sopenharmony_ci/* Array holding vector values describing contents of layers
40e5c31af7Sopenharmony_ci * at subsequent indices.
41e5c31af7Sopenharmony_ci *
42e5c31af7Sopenharmony_ci * Contents of this array are directly related to layered_rendering_fs_code.
43e5c31af7Sopenharmony_ci **/
44e5c31af7Sopenharmony_ciconst unsigned char GeometryShaderLayeredRendering::m_layered_rendering_expected_layer_data[6 * 4] = {
45e5c31af7Sopenharmony_ci	/* Layer 0 */
46e5c31af7Sopenharmony_ci	255, 0, 0, 0,
47e5c31af7Sopenharmony_ci	/* Layer 1 */
48e5c31af7Sopenharmony_ci	0, 255, 0, 0,
49e5c31af7Sopenharmony_ci	/* Layer 2 */
50e5c31af7Sopenharmony_ci	0, 0, 255, 0,
51e5c31af7Sopenharmony_ci	/* Layer 3 */
52e5c31af7Sopenharmony_ci	0, 0, 0, 255,
53e5c31af7Sopenharmony_ci	/* Layer 4 */
54e5c31af7Sopenharmony_ci	255, 255, 0, 0,
55e5c31af7Sopenharmony_ci	/* Layer 5 */
56e5c31af7Sopenharmony_ci	255, 0, 255, 0
57e5c31af7Sopenharmony_ci};
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ci/* Fragment shader code */
60e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_fs_code =
61e5c31af7Sopenharmony_ci	"${VERSION}\n"
62e5c31af7Sopenharmony_ci	"\n"
63e5c31af7Sopenharmony_ci	"precision highp float;\n"
64e5c31af7Sopenharmony_ci	"\n"
65e5c31af7Sopenharmony_ci	"flat in  int  layer_id;\n"
66e5c31af7Sopenharmony_ci	"     out vec4 color;\n"
67e5c31af7Sopenharmony_ci	"\n"
68e5c31af7Sopenharmony_ci	"void main()\n"
69e5c31af7Sopenharmony_ci	"{\n"
70e5c31af7Sopenharmony_ci	"    switch (layer_id)\n"
71e5c31af7Sopenharmony_ci	"    {\n"
72e5c31af7Sopenharmony_ci	"        case 0:  color = vec4(1, 0, 0, 0); break;\n"
73e5c31af7Sopenharmony_ci	"        case 1:  color = vec4(0, 1, 0, 0); break;\n"
74e5c31af7Sopenharmony_ci	"        case 2:  color = vec4(0, 0, 1, 0); break;\n"
75e5c31af7Sopenharmony_ci	"        case 3:  color = vec4(0, 0, 0, 1); break;\n"
76e5c31af7Sopenharmony_ci	"        case 4:  color = vec4(1, 1, 0, 0); break;\n"
77e5c31af7Sopenharmony_ci	"        case 5:  color = vec4(1, 0, 1, 0); break;\n"
78e5c31af7Sopenharmony_ci	"        default: color = vec4(1, 1, 1, 1); break;\n"
79e5c31af7Sopenharmony_ci	"    }\n"
80e5c31af7Sopenharmony_ci	"}\n";
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci/* Geometry shader code parts */
83e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_preamble = "${VERSION}\n"
84e5c31af7Sopenharmony_ci																				   "${GEOMETRY_SHADER_REQUIRE}\n"
85e5c31af7Sopenharmony_ci																				   "\n";
86e5c31af7Sopenharmony_ci
87e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_2d_array = "#define MAX_VERTICES 64\n"
88e5c31af7Sopenharmony_ci																				   "#define N_LAYERS     4\n";
89e5c31af7Sopenharmony_ci
90e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_2d_marray = "#define MAX_VERTICES 64\n"
91e5c31af7Sopenharmony_ci																					"#define N_LAYERS     4\n";
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_3d = "#define MAX_VERTICES 64\n"
94e5c31af7Sopenharmony_ci																			 "#define N_LAYERS     4\n";
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_cm = "#define MAX_VERTICES 96\n"
97e5c31af7Sopenharmony_ci																			 "#define N_LAYERS     6\n";
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci/* NOTE: provoking_vertex_index holds an integer value which represents platform-reported
100e5c31af7Sopenharmony_ci *       GL_LAYER_PROVOKING_VERTEX_EXT value. The meaning is as follows:
101e5c31af7Sopenharmony_ci *
102e5c31af7Sopenharmony_ci *       0: Property carries a GL_UNDEFINED_VERTEX_EXT value. Need to set gl_Layer for all
103e5c31af7Sopenharmony_ci *          vertices.
104e5c31af7Sopenharmony_ci *       1: Property carries a GL_FIRST_VERTEX_CONVENTION_EXT value. Need to set gl_Layer for
105e5c31af7Sopenharmony_ci *          the first two vertices, since these are a part of the two triangles, emitted
106e5c31af7Sopenharmony_ci *          separately for each layer.
107e5c31af7Sopenharmony_ci *       2: Property carries a GL_LAST_VERTEX_CONVENTION_EXT value. Need to set gl_Layer for
108e5c31af7Sopenharmony_ci *          the last two vertices, since these are a part of the two triangles, emitted
109e5c31af7Sopenharmony_ci *          separately for each layer.
110e5c31af7Sopenharmony_ci */
111e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_gs_code_main =
112e5c31af7Sopenharmony_ci	"layout(points)                                    in;\n"
113e5c31af7Sopenharmony_ci	"layout(triangle_strip, max_vertices=MAX_VERTICES) out;\n"
114e5c31af7Sopenharmony_ci	"\n"
115e5c31af7Sopenharmony_ci	"precision highp float;\n"
116e5c31af7Sopenharmony_ci	"\n"
117e5c31af7Sopenharmony_ci	"flat out int layer_id;\n"
118e5c31af7Sopenharmony_ci	"uniform  int provoking_vertex_index;\n"
119e5c31af7Sopenharmony_ci	"\n"
120e5c31af7Sopenharmony_ci	"void main()\n"
121e5c31af7Sopenharmony_ci	"{\n"
122e5c31af7Sopenharmony_ci	"    for (int n = 0; n < N_LAYERS; ++n)\n"
123e5c31af7Sopenharmony_ci	"    {\n"
124e5c31af7Sopenharmony_ci	"        #ifndef SHOULD_NOT_SET_GL_LAYER\n"
125e5c31af7Sopenharmony_ci	"            if (provoking_vertex_index == 0 || provoking_vertex_index == 1) gl_Layer = n;\n"
126e5c31af7Sopenharmony_ci	"        #endif\n"
127e5c31af7Sopenharmony_ci	"\n"
128e5c31af7Sopenharmony_ci	"        layer_id    = gl_Layer;\n"
129e5c31af7Sopenharmony_ci	"        gl_Position = vec4(1, 1, 0, 1);\n"
130e5c31af7Sopenharmony_ci	"        EmitVertex();\n"
131e5c31af7Sopenharmony_ci	"\n"
132e5c31af7Sopenharmony_ci	"        #ifndef SHOULD_NOT_SET_GL_LAYER\n"
133e5c31af7Sopenharmony_ci	"            if (provoking_vertex_index == 0 || provoking_vertex_index == 1) gl_Layer = n;\n"
134e5c31af7Sopenharmony_ci	"        #endif\n"
135e5c31af7Sopenharmony_ci	"\n"
136e5c31af7Sopenharmony_ci	"        layer_id    = gl_Layer;\n"
137e5c31af7Sopenharmony_ci	"        gl_Position = vec4(1, -1, 0, 1);\n"
138e5c31af7Sopenharmony_ci	"        EmitVertex();\n"
139e5c31af7Sopenharmony_ci	"\n"
140e5c31af7Sopenharmony_ci	"        #ifndef SHOULD_NOT_SET_GL_LAYER\n"
141e5c31af7Sopenharmony_ci	"            if (provoking_vertex_index == 0 || provoking_vertex_index == 2) gl_Layer = n;\n"
142e5c31af7Sopenharmony_ci	"        #endif\n"
143e5c31af7Sopenharmony_ci	"\n"
144e5c31af7Sopenharmony_ci	"        layer_id    = gl_Layer;\n"
145e5c31af7Sopenharmony_ci	"        gl_Position = vec4(-1, 1, 0, 1);\n"
146e5c31af7Sopenharmony_ci	"        EmitVertex();\n"
147e5c31af7Sopenharmony_ci	"\n"
148e5c31af7Sopenharmony_ci	"        #ifndef SHOULD_NOT_SET_GL_LAYER\n"
149e5c31af7Sopenharmony_ci	"            gl_Layer = n;\n"
150e5c31af7Sopenharmony_ci	"        #endif\n"
151e5c31af7Sopenharmony_ci	"\n"
152e5c31af7Sopenharmony_ci	"        layer_id    = gl_Layer;\n"
153e5c31af7Sopenharmony_ci	"        gl_Position = vec4(-1, -1, 0, 1);\n"
154e5c31af7Sopenharmony_ci	"        EmitVertex();\n"
155e5c31af7Sopenharmony_ci	"\n"
156e5c31af7Sopenharmony_ci	"        EndPrimitive();\n"
157e5c31af7Sopenharmony_ci	"    }\n"
158e5c31af7Sopenharmony_ci	"}\n";
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ci/* Vertex shader */
161e5c31af7Sopenharmony_ciconst char* GeometryShaderLayeredRendering::m_layered_rendering_vs_code = "${VERSION}\n"
162e5c31af7Sopenharmony_ci																		  "\n"
163e5c31af7Sopenharmony_ci																		  "precision highp float;\n"
164e5c31af7Sopenharmony_ci																		  "\n"
165e5c31af7Sopenharmony_ci																		  "flat out int layer_id;\n"
166e5c31af7Sopenharmony_ci																		  "void main()\n"
167e5c31af7Sopenharmony_ci																		  "{\n"
168e5c31af7Sopenharmony_ci																		  "    layer_id = 0;\n"
169e5c31af7Sopenharmony_ci																		  "}\n";
170e5c31af7Sopenharmony_ci
171e5c31af7Sopenharmony_ci/* Constants used for various test iterations */
172e5c31af7Sopenharmony_ci#define TEXTURE_DEPTH (64)
173e5c31af7Sopenharmony_ci#define TEXTURE_HEIGHT (32)
174e5c31af7Sopenharmony_ci#define TEXTURE_N_COMPONENTS (4)
175e5c31af7Sopenharmony_ci#define TEXTURE_WIDTH (32)
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ci/* Constructor */
178e5c31af7Sopenharmony_ciGeometryShaderLayeredRendering::GeometryShaderLayeredRendering(Context& context, const ExtParameters& extParams,
179e5c31af7Sopenharmony_ci															   const char* name, const char* description)
180e5c31af7Sopenharmony_ci	: TestCaseBase(context, extParams, name, description), m_vao_id(0)
181e5c31af7Sopenharmony_ci{
182e5c31af7Sopenharmony_ci	memset(m_tests, 0, sizeof(m_tests));
183e5c31af7Sopenharmony_ci}
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci/** Builds a GL program specifically for a layer rendering test instance.
186e5c31af7Sopenharmony_ci *
187e5c31af7Sopenharmony_ci *  @param test Layered Rendering test to consider.
188e5c31af7Sopenharmony_ci *
189e5c31af7Sopenharmony_ci *  @return GTFtrue if successful, false otherwise.
190e5c31af7Sopenharmony_ci **/
191e5c31af7Sopenharmony_cibool GeometryShaderLayeredRendering::buildProgramForLRTest(_layered_rendering_test* test)
192e5c31af7Sopenharmony_ci{
193e5c31af7Sopenharmony_ci	return buildProgram(test->po_id, test->fs_id, test->n_fs_parts, test->fs_parts, test->gs_id, test->n_gs_parts,
194e5c31af7Sopenharmony_ci						test->gs_parts, test->vs_id, test->n_vs_parts, test->vs_parts);
195e5c31af7Sopenharmony_ci}
196e5c31af7Sopenharmony_ci
197e5c31af7Sopenharmony_ci/** Executes the test.
198e5c31af7Sopenharmony_ci *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
199e5c31af7Sopenharmony_ci *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
200e5c31af7Sopenharmony_ci *  Note the function throws exception should an error occur!
201e5c31af7Sopenharmony_ci **/
202e5c31af7Sopenharmony_citcu::TestNode::IterateResult GeometryShaderLayeredRendering::iterate(void)
203e5c31af7Sopenharmony_ci{
204e5c31af7Sopenharmony_ci	const glu::ContextType& context_type = m_context.getRenderContext().getType();
205e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
206e5c31af7Sopenharmony_ci
207e5c31af7Sopenharmony_ci	/* Helper variables to support shader compilation process */
208e5c31af7Sopenharmony_ci	const char* cm_fs_parts[] = { m_layered_rendering_fs_code };
209e5c31af7Sopenharmony_ci	const char* cm_gs_parts[] = { m_layered_rendering_gs_code_preamble, m_layered_rendering_gs_code_cm,
210e5c31af7Sopenharmony_ci								  m_layered_rendering_gs_code_main };
211e5c31af7Sopenharmony_ci	const char* cm_vs_parts[]				= { m_layered_rendering_vs_code };
212e5c31af7Sopenharmony_ci	const char* threedimensional_fs_parts[] = { m_layered_rendering_fs_code };
213e5c31af7Sopenharmony_ci	const char* threedimensional_gs_parts[] = { m_layered_rendering_gs_code_preamble, m_layered_rendering_gs_code_3d,
214e5c31af7Sopenharmony_ci												m_layered_rendering_gs_code_main };
215e5c31af7Sopenharmony_ci	const char* threedimensional_vs_parts[] = { m_layered_rendering_vs_code };
216e5c31af7Sopenharmony_ci	const char* twodimensionala_fs_parts[]  = { m_layered_rendering_fs_code };
217e5c31af7Sopenharmony_ci	const char* twodimensionala_gs_parts[]  = { m_layered_rendering_gs_code_preamble,
218e5c31af7Sopenharmony_ci											   m_layered_rendering_gs_code_2d_array, m_layered_rendering_gs_code_main };
219e5c31af7Sopenharmony_ci	const char* twodimensionala_vs_parts[]  = { m_layered_rendering_vs_code };
220e5c31af7Sopenharmony_ci	const char* twodimensionalma_fs_parts[] = { m_layered_rendering_fs_code };
221e5c31af7Sopenharmony_ci	const char* twodimensionalma_gs_parts[] = { m_layered_rendering_gs_code_preamble,
222e5c31af7Sopenharmony_ci												m_layered_rendering_gs_code_2d_marray,
223e5c31af7Sopenharmony_ci												m_layered_rendering_gs_code_main };
224e5c31af7Sopenharmony_ci	const char*		   twodimensionalma_vs_parts[] = { m_layered_rendering_vs_code };
225e5c31af7Sopenharmony_ci	const unsigned int n_cm_fs_parts			   = sizeof(cm_fs_parts) / sizeof(cm_fs_parts[0]);
226e5c31af7Sopenharmony_ci	const unsigned int n_cm_gs_parts			   = sizeof(cm_gs_parts) / sizeof(cm_gs_parts[0]);
227e5c31af7Sopenharmony_ci	const unsigned int n_cm_vs_parts			   = sizeof(cm_vs_parts) / sizeof(cm_vs_parts[0]);
228e5c31af7Sopenharmony_ci	const unsigned int n_threedimensional_fs_parts =
229e5c31af7Sopenharmony_ci		sizeof(threedimensional_fs_parts) / sizeof(threedimensional_fs_parts[0]);
230e5c31af7Sopenharmony_ci	const unsigned int n_threedimensional_gs_parts =
231e5c31af7Sopenharmony_ci		sizeof(threedimensional_gs_parts) / sizeof(threedimensional_gs_parts[0]);
232e5c31af7Sopenharmony_ci	const unsigned int n_threedimensional_vs_parts =
233e5c31af7Sopenharmony_ci		sizeof(threedimensional_vs_parts) / sizeof(threedimensional_vs_parts[0]);
234e5c31af7Sopenharmony_ci	const unsigned int n_twodimensionala_fs_parts =
235e5c31af7Sopenharmony_ci		sizeof(twodimensionala_fs_parts) / sizeof(twodimensionala_fs_parts[0]);
236e5c31af7Sopenharmony_ci	const unsigned int n_twodimensionala_gs_parts =
237e5c31af7Sopenharmony_ci		sizeof(twodimensionala_gs_parts) / sizeof(twodimensionala_gs_parts[0]);
238e5c31af7Sopenharmony_ci	const unsigned int n_twodimensionala_vs_parts =
239e5c31af7Sopenharmony_ci		sizeof(twodimensionala_vs_parts) / sizeof(twodimensionala_vs_parts[0]);
240e5c31af7Sopenharmony_ci	const unsigned int n_twodimensionalma_fs_parts =
241e5c31af7Sopenharmony_ci		sizeof(twodimensionalma_fs_parts) / sizeof(twodimensionalma_fs_parts[0]);
242e5c31af7Sopenharmony_ci	const unsigned int n_twodimensionalma_gs_parts =
243e5c31af7Sopenharmony_ci		sizeof(twodimensionalma_gs_parts) / sizeof(twodimensionalma_gs_parts[0]);
244e5c31af7Sopenharmony_ci	const unsigned int n_twodimensionalma_vs_parts =
245e5c31af7Sopenharmony_ci		sizeof(twodimensionalma_vs_parts) / sizeof(twodimensionalma_vs_parts[0]);
246e5c31af7Sopenharmony_ci
247e5c31af7Sopenharmony_ci	/* General-use helper variables */
248e5c31af7Sopenharmony_ci	unsigned int n_current_test = 0;
249e5c31af7Sopenharmony_ci
250e5c31af7Sopenharmony_ci	/* This test should only run if EXT_geometry_shader is supported */
251e5c31af7Sopenharmony_ci	if (!m_is_geometry_shader_extension_supported)
252e5c31af7Sopenharmony_ci	{
253e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
254e5c31af7Sopenharmony_ci	}
255e5c31af7Sopenharmony_ci
256e5c31af7Sopenharmony_ci	/* Configure test descriptors */
257e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].iteration  = LAYERED_RENDERING_TEST_ITERATION_CUBEMAP;
258e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_layers   = 6; /* faces */
259e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fs_parts   = cm_fs_parts;
260e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].gs_parts   = cm_gs_parts;
261e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].vs_parts   = cm_vs_parts;
262e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_fs_parts = n_cm_fs_parts;
263e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_gs_parts = n_cm_gs_parts;
264e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].n_vs_parts = n_cm_vs_parts;
265e5c31af7Sopenharmony_ci
266e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].iteration  = LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY;
267e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_layers   = 4; /* layers */
268e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fs_parts   = twodimensionala_fs_parts;
269e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].gs_parts   = twodimensionala_gs_parts;
270e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].vs_parts   = twodimensionala_vs_parts;
271e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_fs_parts = n_twodimensionala_fs_parts;
272e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_gs_parts = n_twodimensionala_gs_parts;
273e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].n_vs_parts = n_twodimensionala_vs_parts;
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].iteration  = LAYERED_RENDERING_TEST_ITERATION_3D;
276e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_layers   = 4; /* layers */
277e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fs_parts   = threedimensional_fs_parts;
278e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].gs_parts   = threedimensional_gs_parts;
279e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].vs_parts   = threedimensional_vs_parts;
280e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_fs_parts = n_threedimensional_fs_parts;
281e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_gs_parts = n_threedimensional_gs_parts;
282e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].n_vs_parts = n_threedimensional_vs_parts;
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].iteration =
285e5c31af7Sopenharmony_ci		LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY;
286e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_layers   = 4; /* layers */
287e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fs_parts   = twodimensionalma_fs_parts;
288e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].gs_parts   = twodimensionalma_gs_parts;
289e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].vs_parts   = twodimensionalma_vs_parts;
290e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_fs_parts = n_twodimensionalma_fs_parts;
291e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_gs_parts = n_twodimensionalma_gs_parts;
292e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].n_vs_parts = n_twodimensionalma_vs_parts;
293e5c31af7Sopenharmony_ci
294e5c31af7Sopenharmony_ci	/* Create shader objects we'll use for the test */
295e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fs_id = gl.createShader(GL_FRAGMENT_SHADER);
296e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
297e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].vs_id = gl.createShader(GL_VERTEX_SHADER);
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fs_id = gl.createShader(GL_FRAGMENT_SHADER);
300e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
301e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].vs_id = gl.createShader(GL_VERTEX_SHADER);
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fs_id = gl.createShader(GL_FRAGMENT_SHADER);
304e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
305e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].vs_id = gl.createShader(GL_VERTEX_SHADER);
306e5c31af7Sopenharmony_ci
307e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fs_id = gl.createShader(GL_FRAGMENT_SHADER);
308e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].gs_id =
309e5c31af7Sopenharmony_ci		gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
310e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].vs_id = gl.createShader(GL_VERTEX_SHADER);
311e5c31af7Sopenharmony_ci
312e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create shaders!");
313e5c31af7Sopenharmony_ci
314e5c31af7Sopenharmony_ci	/* Create program objects as well */
315e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].po_id  = gl.createProgram();
316e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].po_id = gl.createProgram();
317e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].po_id		 = gl.createProgram();
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_ci	m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].po_id = gl.createProgram();
320e5c31af7Sopenharmony_ci
321e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create programs!");
322e5c31af7Sopenharmony_ci
323e5c31af7Sopenharmony_ci	/* Build the programs */
324e5c31af7Sopenharmony_ci	if (!buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP]) ||
325e5c31af7Sopenharmony_ci		!buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY]) ||
326e5c31af7Sopenharmony_ci		!buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_3D]) ||
327e5c31af7Sopenharmony_ci		!buildProgramForLRTest(&m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY]))
328e5c31af7Sopenharmony_ci	{
329e5c31af7Sopenharmony_ci		TCU_FAIL("Could not create a program for cube-map texture layered rendering test!");
330e5c31af7Sopenharmony_ci	}
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_ci	/* Set up provoking vertex uniform value, given the GL_LAYER_PROVOKING_VERTEX_EXT value. */
333e5c31af7Sopenharmony_ci	glw::GLint layer_provoking_vertex_gl_value		= -1;
334e5c31af7Sopenharmony_ci	glw::GLint layer_provoking_vertex_uniform_value = -1;
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci	gl.getIntegerv(m_glExtTokens.LAYER_PROVOKING_VERTEX, &layer_provoking_vertex_gl_value);
337e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_LAYER_PROVOKING_VERTEX_EXT pname");
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_ci	if (!glu::isContextTypeES(context_type) && ((glw::GLenum)layer_provoking_vertex_gl_value == GL_PROVOKING_VERTEX))
340e5c31af7Sopenharmony_ci	{
341e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_PROVOKING_VERTEX, &layer_provoking_vertex_gl_value);
342e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_PROVOKING_VERTEX pname");
343e5c31af7Sopenharmony_ci	}
344e5c31af7Sopenharmony_ci
345e5c31af7Sopenharmony_ci	if ((glw::GLenum)layer_provoking_vertex_gl_value == m_glExtTokens.FIRST_VERTEX_CONVENTION)
346e5c31af7Sopenharmony_ci	{
347e5c31af7Sopenharmony_ci		layer_provoking_vertex_uniform_value = 1; /* as per geometry shader implementation */
348e5c31af7Sopenharmony_ci	}
349e5c31af7Sopenharmony_ci	else if ((glw::GLenum)layer_provoking_vertex_gl_value == m_glExtTokens.LAST_VERTEX_CONVENTION)
350e5c31af7Sopenharmony_ci	{
351e5c31af7Sopenharmony_ci		layer_provoking_vertex_uniform_value = 2; /* as per geometry shader implementation */
352e5c31af7Sopenharmony_ci	}
353e5c31af7Sopenharmony_ci	else if ((glw::GLenum)layer_provoking_vertex_gl_value == m_glExtTokens.UNDEFINED_VERTEX)
354e5c31af7Sopenharmony_ci	{
355e5c31af7Sopenharmony_ci		layer_provoking_vertex_uniform_value = 0; /* as per geometry shader implementation */
356e5c31af7Sopenharmony_ci	}
357e5c31af7Sopenharmony_ci	else
358e5c31af7Sopenharmony_ci	{
359e5c31af7Sopenharmony_ci		TCU_FAIL("Unrecognized value returned by glGetIntegerv() for GL_LAYER_PROVOKING_VERTEX_EXT pname.");
360e5c31af7Sopenharmony_ci	}
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci	for (unsigned int test_index = 0; test_index < LAYERED_RENDERING_TEST_ITERATION_LAST; ++test_index)
363e5c31af7Sopenharmony_ci	{
364e5c31af7Sopenharmony_ci		glw::GLint provoking_vertex_index_uniform_location =
365e5c31af7Sopenharmony_ci			gl.getUniformLocation(m_tests[test_index].po_id, "provoking_vertex_index");
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ci		/* Quick checks */
368e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call generated an error");
369e5c31af7Sopenharmony_ci		DE_ASSERT(provoking_vertex_index_uniform_location != -1);
370e5c31af7Sopenharmony_ci
371e5c31af7Sopenharmony_ci		/* Assign the uniform value */
372e5c31af7Sopenharmony_ci		gl.programUniform1i(m_tests[test_index].po_id, provoking_vertex_index_uniform_location,
373e5c31af7Sopenharmony_ci							layer_provoking_vertex_uniform_value);
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramUniform1i() call failed.");
376e5c31af7Sopenharmony_ci	} /* for (all test iterations) */
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci	/* Initialize texture objects */
379e5c31af7Sopenharmony_ci	gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].to_id);
380e5c31af7Sopenharmony_ci	gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].to_id);
381e5c31af7Sopenharmony_ci	gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].to_id);
382e5c31af7Sopenharmony_ci	gl.genTextures(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].to_id);
383e5c31af7Sopenharmony_ci
384e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create texture object(s)!");
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].to_id);
387e5c31af7Sopenharmony_ci	gl.texStorage2D(GL_TEXTURE_CUBE_MAP, 1 /* mip-map only */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].to_id);
390e5c31af7Sopenharmony_ci	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* mip-map only */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
391e5c31af7Sopenharmony_ci
392e5c31af7Sopenharmony_ci	gl.bindTexture(GL_TEXTURE_3D, m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].to_id);
393e5c31af7Sopenharmony_ci	gl.texStorage3D(GL_TEXTURE_3D, 1 /* mip-map only */, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, TEXTURE_DEPTH);
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES,
396e5c31af7Sopenharmony_ci				   m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].to_id);
397e5c31af7Sopenharmony_ci	gl.texStorage3DMultisample(GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES, 1 /* samples */, GL_RGBA8, TEXTURE_WIDTH,
398e5c31af7Sopenharmony_ci							   TEXTURE_HEIGHT, TEXTURE_DEPTH, GL_FALSE /* fixed sample locations */);
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not initialize texture object(s)!");
401e5c31af7Sopenharmony_ci
402e5c31af7Sopenharmony_ci	/* Initialize framebuffer objects */
403e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fbo_id);
404e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fbo_id);
405e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fbo_id);
406e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fbo_id);
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer object(s)!");
409e5c31af7Sopenharmony_ci
410e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].fbo_id);
411e5c31af7Sopenharmony_ci	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
412e5c31af7Sopenharmony_ci						  m_tests[LAYERED_RENDERING_TEST_ITERATION_CUBEMAP].to_id, 0 /* base mip-map */);
413e5c31af7Sopenharmony_ci
414e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].fbo_id);
415e5c31af7Sopenharmony_ci	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
416e5c31af7Sopenharmony_ci						  m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY].to_id, 0 /* base mip-map */);
417e5c31af7Sopenharmony_ci
418e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].fbo_id);
419e5c31af7Sopenharmony_ci	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_tests[LAYERED_RENDERING_TEST_ITERATION_3D].to_id,
420e5c31af7Sopenharmony_ci						  0 /* base mip-map */);
421e5c31af7Sopenharmony_ci
422e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].fbo_id);
423e5c31af7Sopenharmony_ci	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
424e5c31af7Sopenharmony_ci						  m_tests[LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY].to_id, 0 /* base mip-map */);
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure framebuffer object(s)!");
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ci	/* Initialize vertex array object. We don't really use any attributes, but ES does not
429e5c31af7Sopenharmony_ci	 * permit draw calls with an unbound VAO
430e5c31af7Sopenharmony_ci	 */
431e5c31af7Sopenharmony_ci	gl.genVertexArrays(1, &m_vao_id);
432e5c31af7Sopenharmony_ci	gl.bindVertexArray(m_vao_id);
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind a vertex array object!");
435e5c31af7Sopenharmony_ci
436e5c31af7Sopenharmony_ci	/* Execute all iterations */
437e5c31af7Sopenharmony_ci	for (n_current_test = 0; n_current_test < sizeof(m_tests) / sizeof(m_tests[0]); ++n_current_test)
438e5c31af7Sopenharmony_ci	{
439e5c31af7Sopenharmony_ci		unsigned char buffer[TEXTURE_WIDTH * TEXTURE_HEIGHT * TEXTURE_N_COMPONENTS] = { 0 };
440e5c31af7Sopenharmony_ci		glw::GLuint   program_id													= 0;
441e5c31af7Sopenharmony_ci		unsigned int  n_layer														= 0;
442e5c31af7Sopenharmony_ci		glw::GLuint   texture_id													= 0;
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci		/* Bind the iteration-specific framebuffer */
445e5c31af7Sopenharmony_ci		gl.bindFramebuffer(GL_FRAMEBUFFER, m_tests[n_current_test].fbo_id);
446e5c31af7Sopenharmony_ci
447e5c31af7Sopenharmony_ci		program_id = m_tests[n_current_test].po_id;
448e5c31af7Sopenharmony_ci		texture_id = m_tests[n_current_test].to_id;
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_ci		/* Clear the color attachment with (1, 1, 1, 1) which is not used for
451e5c31af7Sopenharmony_ci		 * any layers.
452e5c31af7Sopenharmony_ci		 */
453e5c31af7Sopenharmony_ci		gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
454e5c31af7Sopenharmony_ci		gl.clear(GL_COLOR_BUFFER_BIT);
455e5c31af7Sopenharmony_ci
456e5c31af7Sopenharmony_ci		/* Render a single point. This should result in full-screen quads drawn
457e5c31af7Sopenharmony_ci		 * for each face/layer of the attachment bound to current FBO */
458e5c31af7Sopenharmony_ci		gl.useProgram(program_id);
459e5c31af7Sopenharmony_ci		gl.drawArrays(GL_POINTS, 0 /* first index */, 1 /* n points */);
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "Error rendering geometry!");
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci		/* Read contents of each layer we rendered to and verify the contents */
464e5c31af7Sopenharmony_ci		for (n_layer = 0; n_layer < m_tests[n_current_test].n_layers; ++n_layer)
465e5c31af7Sopenharmony_ci		{
466e5c31af7Sopenharmony_ci			const unsigned char* expected_data =
467e5c31af7Sopenharmony_ci				m_layered_rendering_expected_layer_data + TEXTURE_N_COMPONENTS * n_layer;
468e5c31af7Sopenharmony_ci			unsigned int n				 = 0;
469e5c31af7Sopenharmony_ci			bool		 texture_layered = false;
470e5c31af7Sopenharmony_ci			glw::GLenum  texture_target  = GL_NONE;
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_ci			/* What is the source attachment's texture target? */
473e5c31af7Sopenharmony_ci			switch (m_tests[n_current_test].iteration)
474e5c31af7Sopenharmony_ci			{
475e5c31af7Sopenharmony_ci			case LAYERED_RENDERING_TEST_ITERATION_CUBEMAP:
476e5c31af7Sopenharmony_ci			{
477e5c31af7Sopenharmony_ci				texture_layered = false;
478e5c31af7Sopenharmony_ci				texture_target  = (n_layer == 0) ?
479e5c31af7Sopenharmony_ci									 GL_TEXTURE_CUBE_MAP_POSITIVE_X :
480e5c31af7Sopenharmony_ci									 (n_layer == 1) ?
481e5c31af7Sopenharmony_ci									 GL_TEXTURE_CUBE_MAP_NEGATIVE_X :
482e5c31af7Sopenharmony_ci									 (n_layer == 2) ? GL_TEXTURE_CUBE_MAP_POSITIVE_Y :
483e5c31af7Sopenharmony_ci													  (n_layer == 3) ? GL_TEXTURE_CUBE_MAP_NEGATIVE_Y :
484e5c31af7Sopenharmony_ci																	   (n_layer == 4) ? GL_TEXTURE_CUBE_MAP_POSITIVE_Z :
485e5c31af7Sopenharmony_ci																						GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
486e5c31af7Sopenharmony_ci
487e5c31af7Sopenharmony_ci				break;
488e5c31af7Sopenharmony_ci			}
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ci			case LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY:
491e5c31af7Sopenharmony_ci			{
492e5c31af7Sopenharmony_ci				texture_layered = true;
493e5c31af7Sopenharmony_ci				texture_target  = GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES;
494e5c31af7Sopenharmony_ci
495e5c31af7Sopenharmony_ci				break;
496e5c31af7Sopenharmony_ci			}
497e5c31af7Sopenharmony_ci
498e5c31af7Sopenharmony_ci			case LAYERED_RENDERING_TEST_ITERATION_3D:
499e5c31af7Sopenharmony_ci			{
500e5c31af7Sopenharmony_ci				texture_layered = true;
501e5c31af7Sopenharmony_ci				texture_target  = GL_TEXTURE_3D;
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci				break;
504e5c31af7Sopenharmony_ci			}
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci			case LAYERED_RENDERING_TEST_ITERATION_2D_ARRAY:
507e5c31af7Sopenharmony_ci			{
508e5c31af7Sopenharmony_ci				texture_layered = true;
509e5c31af7Sopenharmony_ci				texture_target  = GL_TEXTURE_2D_ARRAY;
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci				break;
512e5c31af7Sopenharmony_ci			}
513e5c31af7Sopenharmony_ci
514e5c31af7Sopenharmony_ci			default:
515e5c31af7Sopenharmony_ci			{
516e5c31af7Sopenharmony_ci				TCU_FAIL("This location should never be reached");
517e5c31af7Sopenharmony_ci			}
518e5c31af7Sopenharmony_ci			}
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_ci			/* Configure the read framebuffer's read buffer, depending on whether the attachment
521e5c31af7Sopenharmony_ci			 * uses layers or not
522e5c31af7Sopenharmony_ci			 */
523e5c31af7Sopenharmony_ci			if (texture_layered)
524e5c31af7Sopenharmony_ci			{
525e5c31af7Sopenharmony_ci				gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_id, 0 /* base mip-map */,
526e5c31af7Sopenharmony_ci										   n_layer);
527e5c31af7Sopenharmony_ci			}
528e5c31af7Sopenharmony_ci			else
529e5c31af7Sopenharmony_ci			{
530e5c31af7Sopenharmony_ci				if (texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
531e5c31af7Sopenharmony_ci					texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_Y ||
532e5c31af7Sopenharmony_ci					texture_target == GL_TEXTURE_CUBE_MAP_POSITIVE_Z ||
533e5c31af7Sopenharmony_ci					texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_X ||
534e5c31af7Sopenharmony_ci					texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Y ||
535e5c31af7Sopenharmony_ci					texture_target == GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
536e5c31af7Sopenharmony_ci				{
537e5c31af7Sopenharmony_ci					gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, texture_id,
538e5c31af7Sopenharmony_ci											0 /* base mip-map */);
539e5c31af7Sopenharmony_ci				}
540e5c31af7Sopenharmony_ci				else
541e5c31af7Sopenharmony_ci				{
542e5c31af7Sopenharmony_ci					TCU_FAIL("This location should never be reached");
543e5c31af7Sopenharmony_ci				}
544e5c31af7Sopenharmony_ci			}
545e5c31af7Sopenharmony_ci
546e5c31af7Sopenharmony_ci			/* Make sure read framebuffer was configured successfully */
547e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting read framebuffer!");
548e5c31af7Sopenharmony_ci
549e5c31af7Sopenharmony_ci			/* Read the data */
550e5c31af7Sopenharmony_ci			if (m_tests[n_current_test].iteration == LAYERED_RENDERING_TEST_ITERATION_2D_MULTISAMPLE_ARRAY)
551e5c31af7Sopenharmony_ci			{
552e5c31af7Sopenharmony_ci				glw::GLuint new_dst_to = 0;
553e5c31af7Sopenharmony_ci				glw::GLuint dst_fbo_id = 0;
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci				gl.genFramebuffers(1, &dst_fbo_id);
556e5c31af7Sopenharmony_ci
557e5c31af7Sopenharmony_ci				gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_tests[n_current_test].fbo_id);
558e5c31af7Sopenharmony_ci				gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_fbo_id);
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci				gl.genTextures(1, &new_dst_to);
561e5c31af7Sopenharmony_ci				gl.bindTexture(GL_TEXTURE_2D, new_dst_to);
562e5c31af7Sopenharmony_ci				gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT);
563e5c31af7Sopenharmony_ci
564e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(gl.getError(),
565e5c31af7Sopenharmony_ci									"Could not setup texture object for draw framebuffer color attachment.");
566e5c31af7Sopenharmony_ci
567e5c31af7Sopenharmony_ci				gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, new_dst_to, 0);
568e5c31af7Sopenharmony_ci
569e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(gl.getError(),
570e5c31af7Sopenharmony_ci									"Could not attach texture object to draw framebuffer color attachment.");
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ci				gl.blitFramebuffer(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT,
573e5c31af7Sopenharmony_ci								   GL_COLOR_BUFFER_BIT, GL_LINEAR);
574e5c31af7Sopenharmony_ci
575e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(gl.getError(), "Error blitting from read framebuffer to draw framebuffer.");
576e5c31af7Sopenharmony_ci
577e5c31af7Sopenharmony_ci				gl.bindFramebuffer(GL_READ_FRAMEBUFFER, dst_fbo_id);
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_ci				gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
580e5c31af7Sopenharmony_ci
581e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading attachment's data!");
582e5c31af7Sopenharmony_ci
583e5c31af7Sopenharmony_ci				gl.bindFramebuffer(GL_FRAMEBUFFER, m_tests[n_current_test].fbo_id);
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_ci				gl.deleteFramebuffers(1, &dst_fbo_id);
586e5c31af7Sopenharmony_ci				gl.deleteTextures(1, &new_dst_to);
587e5c31af7Sopenharmony_ci			}
588e5c31af7Sopenharmony_ci			else
589e5c31af7Sopenharmony_ci			{
590e5c31af7Sopenharmony_ci				gl.readPixels(0 /* x */, 0 /* y */, TEXTURE_WIDTH, TEXTURE_HEIGHT, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
591e5c31af7Sopenharmony_ci
592e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading attachment's data!");
593e5c31af7Sopenharmony_ci			}
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci			/* Validate it */
596e5c31af7Sopenharmony_ci			for (; n < TEXTURE_WIDTH * TEXTURE_HEIGHT; ++n)
597e5c31af7Sopenharmony_ci			{
598e5c31af7Sopenharmony_ci				unsigned char* data_ptr = buffer + n * TEXTURE_N_COMPONENTS;
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_ci				if (memcmp(data_ptr, expected_data, TEXTURE_N_COMPONENTS) != 0)
601e5c31af7Sopenharmony_ci				{
602e5c31af7Sopenharmony_ci					m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << data_ptr[0] << ", "
603e5c31af7Sopenharmony_ci									   << data_ptr[1] << ", " << data_ptr[2] << ", " << data_ptr[3]
604e5c31af7Sopenharmony_ci									   << "] is different from reference data ["
605e5c31af7Sopenharmony_ci									   << m_layered_rendering_expected_layer_data[0] << ", "
606e5c31af7Sopenharmony_ci									   << m_layered_rendering_expected_layer_data[1] << ", "
607e5c31af7Sopenharmony_ci									   << m_layered_rendering_expected_layer_data[2] << ", "
608e5c31af7Sopenharmony_ci									   << m_layered_rendering_expected_layer_data[3] << "] !"
609e5c31af7Sopenharmony_ci									   << tcu::TestLog::EndMessage;
610e5c31af7Sopenharmony_ci
611e5c31af7Sopenharmony_ci					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
612e5c31af7Sopenharmony_ci					return STOP;
613e5c31af7Sopenharmony_ci				} /* if (data comparison failed) */
614e5c31af7Sopenharmony_ci			}	 /* for (all pixels) */
615e5c31af7Sopenharmony_ci		}		  /* for (all layers) */
616e5c31af7Sopenharmony_ci	}			  /* for (all iterations) */
617e5c31af7Sopenharmony_ci
618e5c31af7Sopenharmony_ci	/* Done! */
619e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
620e5c31af7Sopenharmony_ci	return STOP;
621e5c31af7Sopenharmony_ci}
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci/** Deinitializes GLES objects created during the test.
624e5c31af7Sopenharmony_ci *
625e5c31af7Sopenharmony_ci */
626e5c31af7Sopenharmony_civoid GeometryShaderLayeredRendering::deinit(void)
627e5c31af7Sopenharmony_ci{
628e5c31af7Sopenharmony_ci	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
629e5c31af7Sopenharmony_ci
630e5c31af7Sopenharmony_ci	/* Reset OpenGL ES state */
631e5c31af7Sopenharmony_ci	gl.useProgram(0);
632e5c31af7Sopenharmony_ci	gl.bindTexture(GL_TEXTURE_2D, 0 /* texture */);
633e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
634e5c31af7Sopenharmony_ci	gl.bindVertexArray(0);
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_ci	for (unsigned int n_current_test = 0; n_current_test < sizeof(m_tests) / sizeof(m_tests[0]); ++n_current_test)
637e5c31af7Sopenharmony_ci	{
638e5c31af7Sopenharmony_ci		if (m_tests[n_current_test].po_id != 0)
639e5c31af7Sopenharmony_ci		{
640e5c31af7Sopenharmony_ci			gl.deleteProgram(m_tests[n_current_test].po_id);
641e5c31af7Sopenharmony_ci		}
642e5c31af7Sopenharmony_ci
643e5c31af7Sopenharmony_ci		if (m_tests[n_current_test].fs_id != 0)
644e5c31af7Sopenharmony_ci		{
645e5c31af7Sopenharmony_ci			gl.deleteShader(m_tests[n_current_test].fs_id);
646e5c31af7Sopenharmony_ci		}
647e5c31af7Sopenharmony_ci
648e5c31af7Sopenharmony_ci		if (m_tests[n_current_test].gs_id != 0)
649e5c31af7Sopenharmony_ci		{
650e5c31af7Sopenharmony_ci			gl.deleteShader(m_tests[n_current_test].gs_id);
651e5c31af7Sopenharmony_ci		}
652e5c31af7Sopenharmony_ci
653e5c31af7Sopenharmony_ci		if (m_tests[n_current_test].vs_id != 0)
654e5c31af7Sopenharmony_ci		{
655e5c31af7Sopenharmony_ci			gl.deleteShader(m_tests[n_current_test].vs_id);
656e5c31af7Sopenharmony_ci		}
657e5c31af7Sopenharmony_ci
658e5c31af7Sopenharmony_ci		if (m_tests[n_current_test].to_id != 0)
659e5c31af7Sopenharmony_ci		{
660e5c31af7Sopenharmony_ci			gl.deleteTextures(1, &m_tests[n_current_test].to_id);
661e5c31af7Sopenharmony_ci		}
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_ci		if (m_tests[n_current_test].fbo_id != 0)
664e5c31af7Sopenharmony_ci		{
665e5c31af7Sopenharmony_ci			gl.deleteFramebuffers(1, &m_tests[n_current_test].fbo_id);
666e5c31af7Sopenharmony_ci		}
667e5c31af7Sopenharmony_ci	} /* for (all tests) */
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_ci	if (m_vao_id != 0)
670e5c31af7Sopenharmony_ci	{
671e5c31af7Sopenharmony_ci		gl.deleteVertexArrays(1, &m_vao_id);
672e5c31af7Sopenharmony_ci	}
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci	/* Release base class */
675e5c31af7Sopenharmony_ci	TestCaseBase::deinit();
676e5c31af7Sopenharmony_ci}
677e5c31af7Sopenharmony_ci
678e5c31af7Sopenharmony_ci} // namespace glcts
679