1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 3.0 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
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 Primitive restart tests.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es3fPrimitiveRestartTests.hpp"
25e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
26e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
27e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
28e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
29e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
30e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
31e5c31af7Sopenharmony_ci#include "deRandom.hpp"
32e5c31af7Sopenharmony_ci#include "deMath.h"
33e5c31af7Sopenharmony_ci#include "deString.h"
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ci#include "glw.h"
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ciusing tcu::Vec4;
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_cinamespace deqp
40e5c31af7Sopenharmony_ci{
41e5c31af7Sopenharmony_cinamespace gles3
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_cinamespace Functional
44e5c31af7Sopenharmony_ci{
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_cistatic const int		MAX_RENDER_WIDTH				= 256;
47e5c31af7Sopenharmony_cistatic const int		MAX_RENDER_HEIGHT				= 256;
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_cistatic const deUint32	MAX_UNSIGNED_BYTE				= (1<<8) - 1;
50e5c31af7Sopenharmony_cistatic const deUint32	MAX_UNSIGNED_SHORT				= (1<<16) - 1;
51e5c31af7Sopenharmony_cistatic const deUint32	MAX_UNSIGNED_INT				= (deUint32)((1ULL << 32) - 1);
52e5c31af7Sopenharmony_ci
53e5c31af7Sopenharmony_cistatic const deUint8	RESTART_INDEX_UNSIGNED_BYTE		= (deUint8)MAX_UNSIGNED_BYTE;
54e5c31af7Sopenharmony_cistatic const deUint16	RESTART_INDEX_UNSIGNED_SHORT	= (deUint16)MAX_UNSIGNED_SHORT;
55e5c31af7Sopenharmony_cistatic const deUint32	RESTART_INDEX_UNSIGNED_INT		= MAX_UNSIGNED_INT;
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ciclass PrimitiveRestartCase : public TestCase
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_cipublic:
60e5c31af7Sopenharmony_ci	enum PrimitiveType
61e5c31af7Sopenharmony_ci	{
62e5c31af7Sopenharmony_ci		PRIMITIVE_POINTS = 0,
63e5c31af7Sopenharmony_ci		PRIMITIVE_LINE_STRIP,
64e5c31af7Sopenharmony_ci		PRIMITIVE_LINE_LOOP,
65e5c31af7Sopenharmony_ci		PRIMITIVE_LINES,
66e5c31af7Sopenharmony_ci		PRIMITIVE_TRIANGLE_STRIP,
67e5c31af7Sopenharmony_ci		PRIMITIVE_TRIANGLE_FAN,
68e5c31af7Sopenharmony_ci		PRIMITIVE_TRIANGLES,
69e5c31af7Sopenharmony_ci
70e5c31af7Sopenharmony_ci		PRIMITIVE_LAST
71e5c31af7Sopenharmony_ci	};
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_ci	enum IndexType
74e5c31af7Sopenharmony_ci	{
75e5c31af7Sopenharmony_ci		INDEX_UNSIGNED_BYTE = 0,
76e5c31af7Sopenharmony_ci		INDEX_UNSIGNED_SHORT,
77e5c31af7Sopenharmony_ci		INDEX_UNSIGNED_INT,
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_ci		INDEX_LAST
80e5c31af7Sopenharmony_ci	};
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci	enum Function
83e5c31af7Sopenharmony_ci	{
84e5c31af7Sopenharmony_ci		FUNCTION_DRAW_ELEMENTS = 0,
85e5c31af7Sopenharmony_ci		FUNCTION_DRAW_ELEMENTS_INSTANCED,
86e5c31af7Sopenharmony_ci		FUNCTION_DRAW_RANGE_ELEMENTS,
87e5c31af7Sopenharmony_ci
88e5c31af7Sopenharmony_ci		FUNCTION_LAST
89e5c31af7Sopenharmony_ci	};
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_ci							PrimitiveRestartCase	(Context& context, const char* name, const char* description, PrimitiveType primType, IndexType indexType, Function function, bool beginWithRestart, bool endWithRestart, bool duplicateRestarts);
92e5c31af7Sopenharmony_ci							~PrimitiveRestartCase	(void);
93e5c31af7Sopenharmony_ci
94e5c31af7Sopenharmony_ci	void					init					(void);
95e5c31af7Sopenharmony_ci	void					deinit					(void);
96e5c31af7Sopenharmony_ci	IterateResult			iterate					(void);
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ciprivate:
99e5c31af7Sopenharmony_ci							PrimitiveRestartCase	(const PrimitiveRestartCase& other);
100e5c31af7Sopenharmony_ci	PrimitiveRestartCase&	operator=				(const PrimitiveRestartCase& other);
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ci	void					draw					(int startNdx, int count);
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ci	void					renderWithRestart		(void);
105e5c31af7Sopenharmony_ci	void					renderWithoutRestart	(void);
106e5c31af7Sopenharmony_ci
107e5c31af7Sopenharmony_ci	// Helper functions for handling the appropriate index vector (according to m_indexType).
108e5c31af7Sopenharmony_ci	void					addIndex				(deUint32 index);
109e5c31af7Sopenharmony_ci	deUint32				getIndex				(int indexNdx);
110e5c31af7Sopenharmony_ci	int						getNumIndices			(void);
111e5c31af7Sopenharmony_ci	void*					getIndexPtr				(int indexNdx);
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci	// \note Only one of the following index vectors is used (according to m_indexType).
114e5c31af7Sopenharmony_ci	std::vector<deUint8>	m_indicesUB;
115e5c31af7Sopenharmony_ci	std::vector<deUint16>	m_indicesUS;
116e5c31af7Sopenharmony_ci	std::vector<deUint32>	m_indicesUI;
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci	std::vector<float>		m_positions;
119e5c31af7Sopenharmony_ci
120e5c31af7Sopenharmony_ci	PrimitiveType			m_primType;
121e5c31af7Sopenharmony_ci	IndexType				m_indexType;
122e5c31af7Sopenharmony_ci	Function				m_function;
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci	bool					m_beginWithRestart;		// Whether there will be restart indices at the beginning of the index array.
125e5c31af7Sopenharmony_ci	bool					m_endWithRestart;		// Whether there will be restart indices at the end of the index array.
126e5c31af7Sopenharmony_ci	bool					m_duplicateRestarts;	// Whether two consecutive restarts are used instead of one.
127e5c31af7Sopenharmony_ci
128e5c31af7Sopenharmony_ci	glu::ShaderProgram*		m_program;
129e5c31af7Sopenharmony_ci};
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ciPrimitiveRestartCase::PrimitiveRestartCase (Context& context, const char* name, const char* description, PrimitiveType primType, IndexType indexType, Function function, bool beginWithRestart, bool endWithRestart, bool duplicateRestarts)
132e5c31af7Sopenharmony_ci	: TestCase				(context, name, description)
133e5c31af7Sopenharmony_ci	, m_primType			(primType)
134e5c31af7Sopenharmony_ci	, m_indexType			(indexType)
135e5c31af7Sopenharmony_ci	, m_function			(function)
136e5c31af7Sopenharmony_ci	, m_beginWithRestart	(beginWithRestart)
137e5c31af7Sopenharmony_ci	, m_endWithRestart		(endWithRestart)
138e5c31af7Sopenharmony_ci	, m_duplicateRestarts	(duplicateRestarts)
139e5c31af7Sopenharmony_ci	, m_program				(DE_NULL)
140e5c31af7Sopenharmony_ci{
141e5c31af7Sopenharmony_ci}
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ciPrimitiveRestartCase::~PrimitiveRestartCase (void)
144e5c31af7Sopenharmony_ci{
145e5c31af7Sopenharmony_ci	PrimitiveRestartCase::deinit();
146e5c31af7Sopenharmony_ci}
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_civoid PrimitiveRestartCase::deinit (void)
149e5c31af7Sopenharmony_ci{
150e5c31af7Sopenharmony_ci	delete m_program;
151e5c31af7Sopenharmony_ci	m_program = DE_NULL;
152e5c31af7Sopenharmony_ci}
153e5c31af7Sopenharmony_ci
154e5c31af7Sopenharmony_civoid PrimitiveRestartCase::addIndex (deUint32 index)
155e5c31af7Sopenharmony_ci{
156e5c31af7Sopenharmony_ci	if (m_indexType == INDEX_UNSIGNED_BYTE)
157e5c31af7Sopenharmony_ci	{
158e5c31af7Sopenharmony_ci		DE_ASSERT(de::inRange(index, (deUint32)0, MAX_UNSIGNED_BYTE));
159e5c31af7Sopenharmony_ci		m_indicesUB.push_back((deUint8)index);
160e5c31af7Sopenharmony_ci	}
161e5c31af7Sopenharmony_ci	else if (m_indexType == INDEX_UNSIGNED_SHORT)
162e5c31af7Sopenharmony_ci	{
163e5c31af7Sopenharmony_ci		DE_ASSERT(de::inRange(index, (deUint32)0, MAX_UNSIGNED_SHORT));
164e5c31af7Sopenharmony_ci		m_indicesUS.push_back((deUint16)index);
165e5c31af7Sopenharmony_ci	}
166e5c31af7Sopenharmony_ci	else if (m_indexType == INDEX_UNSIGNED_INT)
167e5c31af7Sopenharmony_ci	{
168e5c31af7Sopenharmony_ci		DE_ASSERT(de::inRange(index, (deUint32)0, MAX_UNSIGNED_INT));
169e5c31af7Sopenharmony_ci		m_indicesUI.push_back((deUint32)index);
170e5c31af7Sopenharmony_ci	}
171e5c31af7Sopenharmony_ci	else
172e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
173e5c31af7Sopenharmony_ci}
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_cideUint32 PrimitiveRestartCase::getIndex (int indexNdx)
176e5c31af7Sopenharmony_ci{
177e5c31af7Sopenharmony_ci	switch (m_indexType)
178e5c31af7Sopenharmony_ci	{
179e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_BYTE:	return (deUint32)m_indicesUB[indexNdx];
180e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_SHORT:	return (deUint32)m_indicesUS[indexNdx];
181e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_INT:	return m_indicesUI[indexNdx];
182e5c31af7Sopenharmony_ci		default:
183e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
184e5c31af7Sopenharmony_ci			return 0;
185e5c31af7Sopenharmony_ci	}
186e5c31af7Sopenharmony_ci}
187e5c31af7Sopenharmony_ci
188e5c31af7Sopenharmony_ciint PrimitiveRestartCase::getNumIndices (void)
189e5c31af7Sopenharmony_ci{
190e5c31af7Sopenharmony_ci	switch (m_indexType)
191e5c31af7Sopenharmony_ci	{
192e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_BYTE:	return (int)m_indicesUB.size();
193e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_SHORT:	return (int)m_indicesUS.size();
194e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_INT:	return (int)m_indicesUI.size();
195e5c31af7Sopenharmony_ci		default:
196e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
197e5c31af7Sopenharmony_ci			return 0;
198e5c31af7Sopenharmony_ci	}
199e5c31af7Sopenharmony_ci}
200e5c31af7Sopenharmony_ci
201e5c31af7Sopenharmony_ci// Pointer to the index value at index indexNdx.
202e5c31af7Sopenharmony_civoid* PrimitiveRestartCase::getIndexPtr (int indexNdx)
203e5c31af7Sopenharmony_ci{
204e5c31af7Sopenharmony_ci	switch (m_indexType)
205e5c31af7Sopenharmony_ci	{
206e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_BYTE:	return (void*)&m_indicesUB[indexNdx];
207e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_SHORT:	return (void*)&m_indicesUS[indexNdx];
208e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_INT:	return (void*)&m_indicesUI[indexNdx];
209e5c31af7Sopenharmony_ci		default:
210e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
211e5c31af7Sopenharmony_ci			return DE_NULL;
212e5c31af7Sopenharmony_ci	}
213e5c31af7Sopenharmony_ci}
214e5c31af7Sopenharmony_ci
215e5c31af7Sopenharmony_civoid PrimitiveRestartCase::init (void)
216e5c31af7Sopenharmony_ci{
217e5c31af7Sopenharmony_ci	// Create shader program.
218e5c31af7Sopenharmony_ci	std::string vertShaderSource;
219e5c31af7Sopenharmony_ci	if (m_primType == PRIMITIVE_POINTS)
220e5c31af7Sopenharmony_ci	{
221e5c31af7Sopenharmony_ci		vertShaderSource =
222e5c31af7Sopenharmony_ci			"#version 300 es\n"
223e5c31af7Sopenharmony_ci			"in highp vec4 a_position;\n"
224e5c31af7Sopenharmony_ci			"\n"
225e5c31af7Sopenharmony_ci			"void main()\n"
226e5c31af7Sopenharmony_ci			"{\n"
227e5c31af7Sopenharmony_ci			"	gl_Position = a_position;\n"
228e5c31af7Sopenharmony_ci			"	gl_PointSize = 1.0f;\n"
229e5c31af7Sopenharmony_ci			"}\n";
230e5c31af7Sopenharmony_ci	}
231e5c31af7Sopenharmony_ci	else
232e5c31af7Sopenharmony_ci	{
233e5c31af7Sopenharmony_ci		vertShaderSource =
234e5c31af7Sopenharmony_ci			"#version 300 es\n"
235e5c31af7Sopenharmony_ci			"in highp vec4 a_position;\n"
236e5c31af7Sopenharmony_ci			"\n"
237e5c31af7Sopenharmony_ci			"void main()\n"
238e5c31af7Sopenharmony_ci			"{\n"
239e5c31af7Sopenharmony_ci			"	gl_Position = a_position;\n"
240e5c31af7Sopenharmony_ci			"}\n";
241e5c31af7Sopenharmony_ci	}
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ci	static const char* fragShaderSource =
244e5c31af7Sopenharmony_ci		"#version 300 es\n"
245e5c31af7Sopenharmony_ci		"layout(location = 0) out mediump vec4 o_color;\n"
246e5c31af7Sopenharmony_ci		"\n"
247e5c31af7Sopenharmony_ci		"void main()\n"
248e5c31af7Sopenharmony_ci		"{\n"
249e5c31af7Sopenharmony_ci		"	o_color = vec4(1.0f);\n"
250e5c31af7Sopenharmony_ci		"}\n";
251e5c31af7Sopenharmony_ci
252e5c31af7Sopenharmony_ci	DE_ASSERT(!m_program);
253e5c31af7Sopenharmony_ci	m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertShaderSource, fragShaderSource));
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ci	if(!m_program->isOk())
256e5c31af7Sopenharmony_ci	{
257e5c31af7Sopenharmony_ci		m_testCtx.getLog() << *m_program;
258e5c31af7Sopenharmony_ci		TCU_FAIL("Failed to compile shader");
259e5c31af7Sopenharmony_ci	}
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_ci	deUint32 restartIndex = m_indexType == INDEX_UNSIGNED_BYTE	? RESTART_INDEX_UNSIGNED_BYTE
262e5c31af7Sopenharmony_ci						  : m_indexType == INDEX_UNSIGNED_SHORT	? RESTART_INDEX_UNSIGNED_SHORT
263e5c31af7Sopenharmony_ci						  : m_indexType == INDEX_UNSIGNED_INT	? RESTART_INDEX_UNSIGNED_INT
264e5c31af7Sopenharmony_ci						  : 0;
265e5c31af7Sopenharmony_ci
266e5c31af7Sopenharmony_ci	DE_ASSERT(restartIndex != 0);
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci	DE_ASSERT(getNumIndices() == 0);
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci	// If testing a case with restart at beginning, add it there.
271e5c31af7Sopenharmony_ci	if (m_beginWithRestart)
272e5c31af7Sopenharmony_ci	{
273e5c31af7Sopenharmony_ci		addIndex(restartIndex);
274e5c31af7Sopenharmony_ci		if (m_duplicateRestarts)
275e5c31af7Sopenharmony_ci			addIndex(restartIndex);
276e5c31af7Sopenharmony_ci	}
277e5c31af7Sopenharmony_ci
278e5c31af7Sopenharmony_ci	// Generate vertex positions and indices depending on primitive type.
279e5c31af7Sopenharmony_ci	// \note At this point, restarts shall not be added to the start or the end of the index vector. Those are special cases, and are done above and after the following if-else chain, respectively.
280e5c31af7Sopenharmony_ci
281e5c31af7Sopenharmony_ci	if (m_primType == PRIMITIVE_POINTS)
282e5c31af7Sopenharmony_ci	{
283e5c31af7Sopenharmony_ci		// Generate rows with different numbers of points.
284e5c31af7Sopenharmony_ci
285e5c31af7Sopenharmony_ci		deUint32	curIndex			= 0;
286e5c31af7Sopenharmony_ci		const int	numRows				= 20;
287e5c31af7Sopenharmony_ci
288e5c31af7Sopenharmony_ci		for (int row = 0; row < numRows; row++)
289e5c31af7Sopenharmony_ci		{
290e5c31af7Sopenharmony_ci			for (int col = 0; col < row + 1; col++)
291e5c31af7Sopenharmony_ci			{
292e5c31af7Sopenharmony_ci				float fx = -1.0f + 2.0f * ((float)col + 0.5f) / (float)numRows;
293e5c31af7Sopenharmony_ci				float fy = -1.0f + 2.0f * ((float)row + 0.5f) / (float)numRows;
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci				m_positions.push_back(fx);
296e5c31af7Sopenharmony_ci				m_positions.push_back(fy);
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci				addIndex(curIndex++);
299e5c31af7Sopenharmony_ci			}
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci			if (row < numRows - 1) // Add a restart after all but last row.
302e5c31af7Sopenharmony_ci			{
303e5c31af7Sopenharmony_ci				addIndex(restartIndex);
304e5c31af7Sopenharmony_ci				if (m_duplicateRestarts)
305e5c31af7Sopenharmony_ci					addIndex(restartIndex);
306e5c31af7Sopenharmony_ci			}
307e5c31af7Sopenharmony_ci		}
308e5c31af7Sopenharmony_ci	}
309e5c31af7Sopenharmony_ci	else if (m_primType == PRIMITIVE_LINE_STRIP || m_primType == PRIMITIVE_LINE_LOOP || m_primType == PRIMITIVE_LINES)
310e5c31af7Sopenharmony_ci	{
311e5c31af7Sopenharmony_ci		// Generate a numRows x numCols arrangement of line polygons of different vertex counts.
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci		deUint32	curIndex	= 0;
314e5c31af7Sopenharmony_ci		const int	numRows		= 4;
315e5c31af7Sopenharmony_ci		const int	numCols		= 4;
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_ci		for (int row = 0; row < numRows; row++)
318e5c31af7Sopenharmony_ci		{
319e5c31af7Sopenharmony_ci			float centerY = -1.0f + 2.0f * ((float)row + 0.5f) / (float)numRows;
320e5c31af7Sopenharmony_ci
321e5c31af7Sopenharmony_ci			for (int col = 0; col < numCols; col++)
322e5c31af7Sopenharmony_ci			{
323e5c31af7Sopenharmony_ci				float	centerX		= -1.0f + 2.0f * ((float)col + 0.5f) / (float)numCols;
324e5c31af7Sopenharmony_ci				int		numVertices	= row*numCols + col + 1;
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ci				for (int i = 0; i < numVertices; i++)
327e5c31af7Sopenharmony_ci				{
328e5c31af7Sopenharmony_ci					float fx = centerX + 0.9f * deFloatCos((float)i*2.0f*DE_PI / (float)numVertices) / (float)numCols;
329e5c31af7Sopenharmony_ci					float fy = centerY + 0.9f * deFloatSin((float)i*2.0f*DE_PI / (float)numVertices) / (float)numRows;
330e5c31af7Sopenharmony_ci
331e5c31af7Sopenharmony_ci					m_positions.push_back(fx);
332e5c31af7Sopenharmony_ci					m_positions.push_back(fy);
333e5c31af7Sopenharmony_ci
334e5c31af7Sopenharmony_ci					addIndex(curIndex++);
335e5c31af7Sopenharmony_ci				}
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_ci				if (col < numCols - 1 || row < numRows - 1) // Add a restart after all but last polygon.
338e5c31af7Sopenharmony_ci				{
339e5c31af7Sopenharmony_ci					addIndex(restartIndex);
340e5c31af7Sopenharmony_ci					if (m_duplicateRestarts)
341e5c31af7Sopenharmony_ci						addIndex(restartIndex);
342e5c31af7Sopenharmony_ci				}
343e5c31af7Sopenharmony_ci			}
344e5c31af7Sopenharmony_ci		}
345e5c31af7Sopenharmony_ci	}
346e5c31af7Sopenharmony_ci	else if (m_primType == PRIMITIVE_TRIANGLE_STRIP)
347e5c31af7Sopenharmony_ci	{
348e5c31af7Sopenharmony_ci		// Generate a number of horizontal triangle strips of different lengths.
349e5c31af7Sopenharmony_ci
350e5c31af7Sopenharmony_ci		deUint32	curIndex	= 0;
351e5c31af7Sopenharmony_ci		const int	numStrips	= 20;
352e5c31af7Sopenharmony_ci
353e5c31af7Sopenharmony_ci		for (int stripNdx = 0; stripNdx < numStrips; stripNdx++)
354e5c31af7Sopenharmony_ci		{
355e5c31af7Sopenharmony_ci			int numVertices = stripNdx + 1;
356e5c31af7Sopenharmony_ci
357e5c31af7Sopenharmony_ci			for (int i = 0; i < numVertices; i++)
358e5c31af7Sopenharmony_ci			{
359e5c31af7Sopenharmony_ci				float fx = -0.9f + 1.8f * (float)(i/2*2) / numStrips;
360e5c31af7Sopenharmony_ci				float fy = -0.9f + 1.8f * ((float)stripNdx + (i%2 == 0 ? 0.0f : 0.8f)) / numStrips;
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci				m_positions.push_back(fx);
363e5c31af7Sopenharmony_ci				m_positions.push_back(fy);
364e5c31af7Sopenharmony_ci
365e5c31af7Sopenharmony_ci				addIndex(curIndex++);
366e5c31af7Sopenharmony_ci			}
367e5c31af7Sopenharmony_ci
368e5c31af7Sopenharmony_ci			if (stripNdx < numStrips - 1) // Add a restart after all but last strip.
369e5c31af7Sopenharmony_ci			{
370e5c31af7Sopenharmony_ci				addIndex(restartIndex);
371e5c31af7Sopenharmony_ci				if (m_duplicateRestarts)
372e5c31af7Sopenharmony_ci					addIndex(restartIndex);
373e5c31af7Sopenharmony_ci			}
374e5c31af7Sopenharmony_ci		}
375e5c31af7Sopenharmony_ci	}
376e5c31af7Sopenharmony_ci	else if (m_primType == PRIMITIVE_TRIANGLE_FAN)
377e5c31af7Sopenharmony_ci	{
378e5c31af7Sopenharmony_ci		// Generate a numRows x numCols arrangement of triangle fan polygons of different vertex counts.
379e5c31af7Sopenharmony_ci
380e5c31af7Sopenharmony_ci		deUint32	curIndex	= 0;
381e5c31af7Sopenharmony_ci		const int	numRows		= 4;
382e5c31af7Sopenharmony_ci		const int	numCols		= 4;
383e5c31af7Sopenharmony_ci
384e5c31af7Sopenharmony_ci		for (int row = 0; row < numRows; row++)
385e5c31af7Sopenharmony_ci		{
386e5c31af7Sopenharmony_ci			float centerY = -1.0f + 2.0f * ((float)row + 0.5f) / (float)numRows;
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci			for (int col = 0; col < numCols; col++)
389e5c31af7Sopenharmony_ci			{
390e5c31af7Sopenharmony_ci				float	centerX			= -1.0f + 2.0f * ((float)col + 0.5f) / (float)numCols;
391e5c31af7Sopenharmony_ci				int		numArcVertices	= row*numCols + col;
392e5c31af7Sopenharmony_ci
393e5c31af7Sopenharmony_ci				m_positions.push_back(centerX);
394e5c31af7Sopenharmony_ci				m_positions.push_back(centerY);
395e5c31af7Sopenharmony_ci
396e5c31af7Sopenharmony_ci				addIndex(curIndex++);
397e5c31af7Sopenharmony_ci
398e5c31af7Sopenharmony_ci				for (int i = 0; i < numArcVertices; i++)
399e5c31af7Sopenharmony_ci				{
400e5c31af7Sopenharmony_ci					float fx = centerX + 0.9f * deFloatCos((float)i*2.0f*DE_PI / (float)numArcVertices) / (float)numCols;
401e5c31af7Sopenharmony_ci					float fy = centerY + 0.9f * deFloatSin((float)i*2.0f*DE_PI / (float)numArcVertices) / (float)numRows;
402e5c31af7Sopenharmony_ci
403e5c31af7Sopenharmony_ci					m_positions.push_back(fx);
404e5c31af7Sopenharmony_ci					m_positions.push_back(fy);
405e5c31af7Sopenharmony_ci
406e5c31af7Sopenharmony_ci					addIndex(curIndex++);
407e5c31af7Sopenharmony_ci				}
408e5c31af7Sopenharmony_ci
409e5c31af7Sopenharmony_ci				if (col < numCols - 1 || row < numRows - 1) // Add a restart after all but last polygon.
410e5c31af7Sopenharmony_ci				{
411e5c31af7Sopenharmony_ci					addIndex(restartIndex);
412e5c31af7Sopenharmony_ci					if (m_duplicateRestarts)
413e5c31af7Sopenharmony_ci						addIndex(restartIndex);
414e5c31af7Sopenharmony_ci				}
415e5c31af7Sopenharmony_ci			}
416e5c31af7Sopenharmony_ci		}
417e5c31af7Sopenharmony_ci	}
418e5c31af7Sopenharmony_ci	else if (m_primType == PRIMITIVE_TRIANGLES)
419e5c31af7Sopenharmony_ci	{
420e5c31af7Sopenharmony_ci		// Generate a number of rows with (potentially incomplete) triangles.
421e5c31af7Sopenharmony_ci
422e5c31af7Sopenharmony_ci		deUint32	curIndex	= 0;
423e5c31af7Sopenharmony_ci		const int	numRows		= 3*7;
424e5c31af7Sopenharmony_ci
425e5c31af7Sopenharmony_ci		for (int rowNdx = 0; rowNdx < numRows; rowNdx++)
426e5c31af7Sopenharmony_ci		{
427e5c31af7Sopenharmony_ci			int numVertices = rowNdx + 1;
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci			for (int i = 0; i < numVertices; i++)
430e5c31af7Sopenharmony_ci			{
431e5c31af7Sopenharmony_ci				float fx = -0.9f + 1.8f * ((float)(i/3) + (i%3 == 2 ? 0.8f : 0.0f)) * 3 / numRows;
432e5c31af7Sopenharmony_ci				float fy = -0.9f + 1.8f * ((float)rowNdx + (i%3 == 0 ? 0.0f : 0.8f)) / numRows;
433e5c31af7Sopenharmony_ci
434e5c31af7Sopenharmony_ci				m_positions.push_back(fx);
435e5c31af7Sopenharmony_ci				m_positions.push_back(fy);
436e5c31af7Sopenharmony_ci
437e5c31af7Sopenharmony_ci				addIndex(curIndex++);
438e5c31af7Sopenharmony_ci			}
439e5c31af7Sopenharmony_ci
440e5c31af7Sopenharmony_ci			if (rowNdx < numRows - 1) // Add a restart after all but last row.
441e5c31af7Sopenharmony_ci			{
442e5c31af7Sopenharmony_ci				addIndex(restartIndex);
443e5c31af7Sopenharmony_ci				if (m_duplicateRestarts)
444e5c31af7Sopenharmony_ci					addIndex(restartIndex);
445e5c31af7Sopenharmony_ci			}
446e5c31af7Sopenharmony_ci		}
447e5c31af7Sopenharmony_ci	}
448e5c31af7Sopenharmony_ci	else
449e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
450e5c31af7Sopenharmony_ci
451e5c31af7Sopenharmony_ci	// If testing a case with restart at end, add it there.
452e5c31af7Sopenharmony_ci	if (m_endWithRestart)
453e5c31af7Sopenharmony_ci	{
454e5c31af7Sopenharmony_ci		addIndex(restartIndex);
455e5c31af7Sopenharmony_ci		if (m_duplicateRestarts)
456e5c31af7Sopenharmony_ci			addIndex(restartIndex);
457e5c31af7Sopenharmony_ci	}
458e5c31af7Sopenharmony_ci
459e5c31af7Sopenharmony_ci	// Special case assertions.
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ci	int numIndices = getNumIndices();
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	DE_ASSERT(numIndices > 0);
464e5c31af7Sopenharmony_ci	DE_ASSERT(m_beginWithRestart || getIndex(0) != restartIndex);						// We don't want restarts at beginning unless the case is a special case.
465e5c31af7Sopenharmony_ci	DE_ASSERT(m_endWithRestart || getIndex(numIndices-1) != restartIndex);			// We don't want restarts at end unless the case is a special case.
466e5c31af7Sopenharmony_ci
467e5c31af7Sopenharmony_ci	if (!m_duplicateRestarts)
468e5c31af7Sopenharmony_ci		for (int i = 1; i < numIndices; i++)
469e5c31af7Sopenharmony_ci			DE_ASSERT(getIndex(i) != restartIndex || getIndex(i-1) != restartIndex);	// We don't want duplicate restarts unless the case is a special case.
470e5c31af7Sopenharmony_ci}
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_ciPrimitiveRestartCase::IterateResult PrimitiveRestartCase::iterate (void)
473e5c31af7Sopenharmony_ci{
474e5c31af7Sopenharmony_ci	int							width			= deMin32(m_context.getRenderTarget().getWidth(), MAX_RENDER_WIDTH);
475e5c31af7Sopenharmony_ci	int							height			= deMin32(m_context.getRenderTarget().getHeight(), MAX_RENDER_HEIGHT);
476e5c31af7Sopenharmony_ci
477e5c31af7Sopenharmony_ci	int							xOffsetMax		= m_context.getRenderTarget().getWidth() - width;
478e5c31af7Sopenharmony_ci	int							yOffsetMax		= m_context.getRenderTarget().getHeight() - height;
479e5c31af7Sopenharmony_ci
480e5c31af7Sopenharmony_ci	de::Random					rnd				(deStringHash(getName()));
481e5c31af7Sopenharmony_ci
482e5c31af7Sopenharmony_ci	int							xOffset			= rnd.getInt(0, xOffsetMax);
483e5c31af7Sopenharmony_ci	int							yOffset			= rnd.getInt(0, yOffsetMax);
484e5c31af7Sopenharmony_ci	tcu::Surface				referenceImg	(width, height);
485e5c31af7Sopenharmony_ci	tcu::Surface				resultImg		(width, height);
486e5c31af7Sopenharmony_ci
487e5c31af7Sopenharmony_ci	glViewport(xOffset, yOffset, width, height);
488e5c31af7Sopenharmony_ci	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
489e5c31af7Sopenharmony_ci
490e5c31af7Sopenharmony_ci	deUint32 program = m_program->getProgram();
491e5c31af7Sopenharmony_ci	glUseProgram(program);
492e5c31af7Sopenharmony_ci
493e5c31af7Sopenharmony_ci	// Setup position attribute.
494e5c31af7Sopenharmony_ci
495e5c31af7Sopenharmony_ci	int loc = glGetAttribLocation(program, "a_position");
496e5c31af7Sopenharmony_ci	glEnableVertexAttribArray(loc);
497e5c31af7Sopenharmony_ci	glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, &m_positions[0]);
498e5c31af7Sopenharmony_ci
499e5c31af7Sopenharmony_ci	// Render result.
500e5c31af7Sopenharmony_ci
501e5c31af7Sopenharmony_ci	renderWithRestart();
502e5c31af7Sopenharmony_ci	glu::readPixels(m_context.getRenderContext(), xOffset, yOffset, resultImg.getAccess());
503e5c31af7Sopenharmony_ci
504e5c31af7Sopenharmony_ci	// Render reference (same scene as the real deal, but emulate primitive restart without actually using it).
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci	renderWithoutRestart();
507e5c31af7Sopenharmony_ci	glu::readPixels(m_context.getRenderContext(), xOffset, yOffset, referenceImg.getAccess());
508e5c31af7Sopenharmony_ci
509e5c31af7Sopenharmony_ci	// Compare.
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci	bool testOk = tcu::pixelThresholdCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", referenceImg, resultImg, tcu::RGBA(0, 0, 0, 0), tcu::COMPARE_LOG_RESULT);
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(testOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
514e5c31af7Sopenharmony_ci							testOk ? "Pass"					: "Fail");
515e5c31af7Sopenharmony_ci
516e5c31af7Sopenharmony_ci	glUseProgram(0);
517e5c31af7Sopenharmony_ci
518e5c31af7Sopenharmony_ci	return STOP;
519e5c31af7Sopenharmony_ci}
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_ci// Draw with the appropriate GLES3 draw function.
522e5c31af7Sopenharmony_civoid PrimitiveRestartCase::draw (int startNdx, int count)
523e5c31af7Sopenharmony_ci{
524e5c31af7Sopenharmony_ci	GLenum primTypeGL;
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci	switch (m_primType)
527e5c31af7Sopenharmony_ci	{
528e5c31af7Sopenharmony_ci		case PRIMITIVE_POINTS:			primTypeGL = GL_POINTS;			break;
529e5c31af7Sopenharmony_ci		case PRIMITIVE_LINE_STRIP:		primTypeGL = GL_LINE_STRIP;		break;
530e5c31af7Sopenharmony_ci		case PRIMITIVE_LINE_LOOP:		primTypeGL = GL_LINE_LOOP;		break;
531e5c31af7Sopenharmony_ci		case PRIMITIVE_LINES:			primTypeGL = GL_LINES;			break;
532e5c31af7Sopenharmony_ci		case PRIMITIVE_TRIANGLE_STRIP:	primTypeGL = GL_TRIANGLE_STRIP;	break;
533e5c31af7Sopenharmony_ci		case PRIMITIVE_TRIANGLE_FAN:	primTypeGL = GL_TRIANGLE_FAN;	break;
534e5c31af7Sopenharmony_ci		case PRIMITIVE_TRIANGLES:		primTypeGL = GL_TRIANGLES;		break;
535e5c31af7Sopenharmony_ci		default:
536e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
537e5c31af7Sopenharmony_ci			primTypeGL = 0;
538e5c31af7Sopenharmony_ci	}
539e5c31af7Sopenharmony_ci
540e5c31af7Sopenharmony_ci	GLenum indexTypeGL;
541e5c31af7Sopenharmony_ci
542e5c31af7Sopenharmony_ci	switch (m_indexType)
543e5c31af7Sopenharmony_ci	{
544e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_BYTE:	indexTypeGL = GL_UNSIGNED_BYTE;		break;
545e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_SHORT:	indexTypeGL = GL_UNSIGNED_SHORT;	break;
546e5c31af7Sopenharmony_ci		case INDEX_UNSIGNED_INT:	indexTypeGL = GL_UNSIGNED_INT;		break;
547e5c31af7Sopenharmony_ci		default:
548e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
549e5c31af7Sopenharmony_ci			indexTypeGL = 0;
550e5c31af7Sopenharmony_ci	}
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	deUint32 restartIndex = m_indexType == INDEX_UNSIGNED_BYTE	? RESTART_INDEX_UNSIGNED_BYTE
553e5c31af7Sopenharmony_ci						  : m_indexType == INDEX_UNSIGNED_SHORT	? RESTART_INDEX_UNSIGNED_SHORT
554e5c31af7Sopenharmony_ci						  : m_indexType == INDEX_UNSIGNED_INT	? RESTART_INDEX_UNSIGNED_INT
555e5c31af7Sopenharmony_ci						  : 0;
556e5c31af7Sopenharmony_ci
557e5c31af7Sopenharmony_ci	DE_ASSERT(restartIndex != 0);
558e5c31af7Sopenharmony_ci
559e5c31af7Sopenharmony_ci	if (m_function == FUNCTION_DRAW_ELEMENTS)
560e5c31af7Sopenharmony_ci		glDrawElements(primTypeGL, (GLsizei)count, indexTypeGL, (GLvoid*)getIndexPtr(startNdx));
561e5c31af7Sopenharmony_ci	else if (m_function == FUNCTION_DRAW_ELEMENTS_INSTANCED)
562e5c31af7Sopenharmony_ci		glDrawElementsInstanced(primTypeGL, (GLsizei)count, indexTypeGL, (GLvoid*)getIndexPtr(startNdx), 1);
563e5c31af7Sopenharmony_ci	else
564e5c31af7Sopenharmony_ci	{
565e5c31af7Sopenharmony_ci		DE_ASSERT(m_function == FUNCTION_DRAW_RANGE_ELEMENTS);
566e5c31af7Sopenharmony_ci
567e5c31af7Sopenharmony_ci		// Find the largest non-restart index in the index array (for glDrawRangeElements() end parameter).
568e5c31af7Sopenharmony_ci
569e5c31af7Sopenharmony_ci		deUint32 max = 0;
570e5c31af7Sopenharmony_ci
571e5c31af7Sopenharmony_ci		int numIndices = getNumIndices();
572e5c31af7Sopenharmony_ci		for (int i = 0; i < numIndices; i++)
573e5c31af7Sopenharmony_ci		{
574e5c31af7Sopenharmony_ci			deUint32 index = getIndex(i);
575e5c31af7Sopenharmony_ci			if (index != restartIndex && index > max)
576e5c31af7Sopenharmony_ci				max = index;
577e5c31af7Sopenharmony_ci		}
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_ci		glDrawRangeElements(primTypeGL, 0, (GLuint)max, (GLsizei)count, indexTypeGL, (GLvoid*)getIndexPtr(startNdx));
580e5c31af7Sopenharmony_ci	}
581e5c31af7Sopenharmony_ci}
582e5c31af7Sopenharmony_ci
583e5c31af7Sopenharmony_civoid PrimitiveRestartCase::renderWithRestart (void)
584e5c31af7Sopenharmony_ci{
585e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("PrimitiveRestartCase::renderWithRestart() begin");
586e5c31af7Sopenharmony_ci
587e5c31af7Sopenharmony_ci	glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
588e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("Enable primitive restart");
589e5c31af7Sopenharmony_ci	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
590e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("Clear in PrimitiveRestartCase::renderWithRestart()");
591e5c31af7Sopenharmony_ci
592e5c31af7Sopenharmony_ci	draw(0, getNumIndices());
593e5c31af7Sopenharmony_ci
594e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("Draw in PrimitiveRestartCase::renderWithRestart()");
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("PrimitiveRestartCase::renderWithRestart() end");
597e5c31af7Sopenharmony_ci}
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_civoid PrimitiveRestartCase::renderWithoutRestart (void)
600e5c31af7Sopenharmony_ci{
601e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("PrimitiveRestartCase::renderWithoutRestart() begin");
602e5c31af7Sopenharmony_ci
603e5c31af7Sopenharmony_ci	deUint32 restartIndex = m_indexType == INDEX_UNSIGNED_BYTE	? RESTART_INDEX_UNSIGNED_BYTE
604e5c31af7Sopenharmony_ci						  : m_indexType == INDEX_UNSIGNED_SHORT	? RESTART_INDEX_UNSIGNED_SHORT
605e5c31af7Sopenharmony_ci						  : m_indexType == INDEX_UNSIGNED_INT	? RESTART_INDEX_UNSIGNED_INT
606e5c31af7Sopenharmony_ci						  : 0;
607e5c31af7Sopenharmony_ci
608e5c31af7Sopenharmony_ci	DE_ASSERT(restartIndex != 0);
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ci	glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
611e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("Disable primitive restart");
612e5c31af7Sopenharmony_ci	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
613e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("Clear in PrimitiveRestartCase::renderWithoutRestart()");
614e5c31af7Sopenharmony_ci
615e5c31af7Sopenharmony_ci	// Draw, emulating primitive restart.
616e5c31af7Sopenharmony_ci
617e5c31af7Sopenharmony_ci	int numIndices = getNumIndices();
618e5c31af7Sopenharmony_ci
619e5c31af7Sopenharmony_ci	DE_ASSERT(numIndices >= 0);
620e5c31af7Sopenharmony_ci
621e5c31af7Sopenharmony_ci	int indexArrayStartNdx = 0; // Keep track of the draw start index - first index after a primitive restart, or initially the first index altogether.
622e5c31af7Sopenharmony_ci
623e5c31af7Sopenharmony_ci	for (int indexArrayNdx = 0; indexArrayNdx <= numIndices; indexArrayNdx++) // \note Goes one "too far" in order to detect end of array as well.
624e5c31af7Sopenharmony_ci	{
625e5c31af7Sopenharmony_ci		if (indexArrayNdx >= numIndices || getIndex(indexArrayNdx) == restartIndex) // \note Handle end of array the same way as a restart index encounter.
626e5c31af7Sopenharmony_ci		{
627e5c31af7Sopenharmony_ci			if (indexArrayStartNdx < numIndices)
628e5c31af7Sopenharmony_ci			{
629e5c31af7Sopenharmony_ci				// Draw from index indexArrayStartNdx to index indexArrayNdx-1 .
630e5c31af7Sopenharmony_ci
631e5c31af7Sopenharmony_ci				draw(indexArrayStartNdx, indexArrayNdx - indexArrayStartNdx);
632e5c31af7Sopenharmony_ci				GLU_CHECK_MSG("Draw in PrimitiveRestartCase::renderWithoutRestart()");
633e5c31af7Sopenharmony_ci			}
634e5c31af7Sopenharmony_ci
635e5c31af7Sopenharmony_ci			indexArrayStartNdx = indexArrayNdx + 1; // Next draw starts just after this restart index.
636e5c31af7Sopenharmony_ci		}
637e5c31af7Sopenharmony_ci	}
638e5c31af7Sopenharmony_ci
639e5c31af7Sopenharmony_ci	GLU_CHECK_MSG("PrimitiveRestartCase::renderWithoutRestart() end");
640e5c31af7Sopenharmony_ci}
641e5c31af7Sopenharmony_ci
642e5c31af7Sopenharmony_ciPrimitiveRestartTests::PrimitiveRestartTests (Context& context)
643e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "primitive_restart", "Primitive restart tests")
644e5c31af7Sopenharmony_ci{
645e5c31af7Sopenharmony_ci}
646e5c31af7Sopenharmony_ci
647e5c31af7Sopenharmony_ciPrimitiveRestartTests::~PrimitiveRestartTests (void)
648e5c31af7Sopenharmony_ci{
649e5c31af7Sopenharmony_ci}
650e5c31af7Sopenharmony_ci
651e5c31af7Sopenharmony_civoid PrimitiveRestartTests::init (void)
652e5c31af7Sopenharmony_ci{
653e5c31af7Sopenharmony_ci	for (int isRestartBeginCaseI = 0; isRestartBeginCaseI <= 1; isRestartBeginCaseI++)
654e5c31af7Sopenharmony_ci	for (int isRestartEndCaseI = 0; isRestartEndCaseI <= 1; isRestartEndCaseI++)
655e5c31af7Sopenharmony_ci	for (int isDuplicateRestartCaseI = 0; isDuplicateRestartCaseI <= 1; isDuplicateRestartCaseI++)
656e5c31af7Sopenharmony_ci	{
657e5c31af7Sopenharmony_ci		bool			isRestartBeginCase		= isRestartBeginCaseI != 0;
658e5c31af7Sopenharmony_ci		bool			isRestartEndCase		= isRestartEndCaseI != 0;
659e5c31af7Sopenharmony_ci		bool			isDuplicateRestartCase	= isDuplicateRestartCaseI != 0;
660e5c31af7Sopenharmony_ci
661e5c31af7Sopenharmony_ci		std::string		specialCaseGroupName;
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_ci		if (isRestartBeginCase)		specialCaseGroupName = "begin_restart";
664e5c31af7Sopenharmony_ci		if (isRestartEndCase)		specialCaseGroupName += std::string(specialCaseGroupName.empty() ? "" : "_") + "end_restart";
665e5c31af7Sopenharmony_ci		if (isDuplicateRestartCase)	specialCaseGroupName += std::string(specialCaseGroupName.empty() ? "" : "_") + "duplicate_restarts";
666e5c31af7Sopenharmony_ci
667e5c31af7Sopenharmony_ci		if (specialCaseGroupName.empty())
668e5c31af7Sopenharmony_ci			specialCaseGroupName = "basic";
669e5c31af7Sopenharmony_ci
670e5c31af7Sopenharmony_ci		TestCaseGroup* specialCaseGroup = new TestCaseGroup(m_context, specialCaseGroupName.c_str(), "");
671e5c31af7Sopenharmony_ci		addChild(specialCaseGroup);
672e5c31af7Sopenharmony_ci
673e5c31af7Sopenharmony_ci		for (int primType = 0; primType < (int)PrimitiveRestartCase::PRIMITIVE_LAST; primType++)
674e5c31af7Sopenharmony_ci		{
675e5c31af7Sopenharmony_ci			const char* primTypeName = primType == (int)PrimitiveRestartCase::PRIMITIVE_POINTS			? "points"
676e5c31af7Sopenharmony_ci									 : primType == (int)PrimitiveRestartCase::PRIMITIVE_LINE_STRIP		? "line_strip"
677e5c31af7Sopenharmony_ci									 : primType == (int)PrimitiveRestartCase::PRIMITIVE_LINE_LOOP		? "line_loop"
678e5c31af7Sopenharmony_ci									 : primType == (int)PrimitiveRestartCase::PRIMITIVE_LINES			? "lines"
679e5c31af7Sopenharmony_ci									 : primType == (int)PrimitiveRestartCase::PRIMITIVE_TRIANGLE_STRIP	? "triangle_strip"
680e5c31af7Sopenharmony_ci									 : primType == (int)PrimitiveRestartCase::PRIMITIVE_TRIANGLE_FAN	? "triangle_fan"
681e5c31af7Sopenharmony_ci									 : primType == (int)PrimitiveRestartCase::PRIMITIVE_TRIANGLES		? "triangles"
682e5c31af7Sopenharmony_ci									 : DE_NULL;
683e5c31af7Sopenharmony_ci
684e5c31af7Sopenharmony_ci			DE_ASSERT(primTypeName != DE_NULL);
685e5c31af7Sopenharmony_ci
686e5c31af7Sopenharmony_ci			TestCaseGroup* primTypeGroup = new TestCaseGroup(m_context, primTypeName, "");
687e5c31af7Sopenharmony_ci			specialCaseGroup->addChild(primTypeGroup);
688e5c31af7Sopenharmony_ci
689e5c31af7Sopenharmony_ci			for (int indexType = 0; indexType < (int)PrimitiveRestartCase::INDEX_LAST; indexType++)
690e5c31af7Sopenharmony_ci			{
691e5c31af7Sopenharmony_ci				const char *indexTypeName = indexType == (int)PrimitiveRestartCase::INDEX_UNSIGNED_BYTE		? "unsigned_byte"
692e5c31af7Sopenharmony_ci										  : indexType == (int)PrimitiveRestartCase::INDEX_UNSIGNED_SHORT	? "unsigned_short"
693e5c31af7Sopenharmony_ci										  : indexType == (int)PrimitiveRestartCase::INDEX_UNSIGNED_INT		? "unsigned_int"
694e5c31af7Sopenharmony_ci										  : DE_NULL;
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci				DE_ASSERT(indexTypeName != DE_NULL);
697e5c31af7Sopenharmony_ci
698e5c31af7Sopenharmony_ci				TestCaseGroup* indexTypeGroup = new TestCaseGroup(m_context, indexTypeName, "");
699e5c31af7Sopenharmony_ci				primTypeGroup->addChild(indexTypeGroup);
700e5c31af7Sopenharmony_ci
701e5c31af7Sopenharmony_ci				for (int function = 0; function < (int)PrimitiveRestartCase::FUNCTION_LAST; function++)
702e5c31af7Sopenharmony_ci				{
703e5c31af7Sopenharmony_ci					const char* functionName = function == (int)PrimitiveRestartCase::FUNCTION_DRAW_ELEMENTS			? "draw_elements"
704e5c31af7Sopenharmony_ci											 : function == (int)PrimitiveRestartCase::FUNCTION_DRAW_ELEMENTS_INSTANCED	? "draw_elements_instanced"
705e5c31af7Sopenharmony_ci											 : function == (int)PrimitiveRestartCase::FUNCTION_DRAW_RANGE_ELEMENTS		? "draw_range_elements"
706e5c31af7Sopenharmony_ci											 : DE_NULL;
707e5c31af7Sopenharmony_ci
708e5c31af7Sopenharmony_ci					DE_ASSERT(functionName != DE_NULL);
709e5c31af7Sopenharmony_ci
710e5c31af7Sopenharmony_ci					indexTypeGroup->addChild(new PrimitiveRestartCase(m_context,
711e5c31af7Sopenharmony_ci																	  functionName,
712e5c31af7Sopenharmony_ci																	  "",
713e5c31af7Sopenharmony_ci																	  (PrimitiveRestartCase::PrimitiveType)primType,
714e5c31af7Sopenharmony_ci																	  (PrimitiveRestartCase::IndexType)indexType,
715e5c31af7Sopenharmony_ci																	  (PrimitiveRestartCase::Function)function,
716e5c31af7Sopenharmony_ci																	  isRestartBeginCase,
717e5c31af7Sopenharmony_ci																	  isRestartEndCase,
718e5c31af7Sopenharmony_ci																	  isDuplicateRestartCase));
719e5c31af7Sopenharmony_ci				}
720e5c31af7Sopenharmony_ci			}
721e5c31af7Sopenharmony_ci		}
722e5c31af7Sopenharmony_ci	}
723e5c31af7Sopenharmony_ci}
724e5c31af7Sopenharmony_ci
725e5c31af7Sopenharmony_ci} // Functional
726e5c31af7Sopenharmony_ci} // gles3
727e5c31af7Sopenharmony_ci} // deqp
728