1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL (ES) 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 Draw tests
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "glsDrawTest.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "deRandom.h"
27e5c31af7Sopenharmony_ci#include "deRandom.hpp"
28e5c31af7Sopenharmony_ci#include "deMath.h"
29e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
30e5c31af7Sopenharmony_ci#include "deFloat16.h"
31e5c31af7Sopenharmony_ci#include "deUniquePtr.hpp"
32e5c31af7Sopenharmony_ci#include "deArrayUtil.hpp"
33e5c31af7Sopenharmony_ci
34e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
35e5c31af7Sopenharmony_ci#include "tcuPixelFormat.hpp"
36e5c31af7Sopenharmony_ci#include "tcuRGBA.hpp"
37e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
38e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
39e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
40e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
41e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
42e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
43e5c31af7Sopenharmony_ci#include "tcuFloat.hpp"
44e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
47e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
48e5c31af7Sopenharmony_ci#include "gluCallLogWrapper.hpp"
49e5c31af7Sopenharmony_ci
50e5c31af7Sopenharmony_ci#include "sglrContext.hpp"
51e5c31af7Sopenharmony_ci#include "sglrReferenceContext.hpp"
52e5c31af7Sopenharmony_ci#include "sglrGLContext.hpp"
53e5c31af7Sopenharmony_ci
54e5c31af7Sopenharmony_ci#include "rrGenericVector.hpp"
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_ci#include <cstring>
57e5c31af7Sopenharmony_ci#include <cmath>
58e5c31af7Sopenharmony_ci#include <vector>
59e5c31af7Sopenharmony_ci#include <sstream>
60e5c31af7Sopenharmony_ci#include <limits>
61e5c31af7Sopenharmony_ci#include <cstdint>
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ci#include "glwDefs.hpp"
64e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
65e5c31af7Sopenharmony_ci
66e5c31af7Sopenharmony_cinamespace deqp
67e5c31af7Sopenharmony_ci{
68e5c31af7Sopenharmony_cinamespace gls
69e5c31af7Sopenharmony_ci{
70e5c31af7Sopenharmony_cinamespace
71e5c31af7Sopenharmony_ci{
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_ciusing tcu::TestLog;
74e5c31af7Sopenharmony_ciusing namespace glw; // GL types
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ciconst int MAX_RENDER_TARGET_SIZE = 512;
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci// Utils
79e5c31af7Sopenharmony_ci
80e5c31af7Sopenharmony_cistatic GLenum targetToGL (DrawTestSpec::Target target)
81e5c31af7Sopenharmony_ci{
82e5c31af7Sopenharmony_ci	static const GLenum targets[] =
83e5c31af7Sopenharmony_ci	{
84e5c31af7Sopenharmony_ci		GL_ELEMENT_ARRAY_BUFFER,	// TARGET_ELEMENT_ARRAY = 0,
85e5c31af7Sopenharmony_ci		GL_ARRAY_BUFFER				// TARGET_ARRAY,
86e5c31af7Sopenharmony_ci	};
87e5c31af7Sopenharmony_ci
88e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::TARGET_LAST>(targets, (int)target);
89e5c31af7Sopenharmony_ci}
90e5c31af7Sopenharmony_ci
91e5c31af7Sopenharmony_cistatic GLenum usageToGL (DrawTestSpec::Usage usage)
92e5c31af7Sopenharmony_ci{
93e5c31af7Sopenharmony_ci	static const GLenum usages[] =
94e5c31af7Sopenharmony_ci	{
95e5c31af7Sopenharmony_ci		GL_DYNAMIC_DRAW,	// USAGE_DYNAMIC_DRAW = 0,
96e5c31af7Sopenharmony_ci		GL_STATIC_DRAW,		// USAGE_STATIC_DRAW,
97e5c31af7Sopenharmony_ci		GL_STREAM_DRAW,		// USAGE_STREAM_DRAW,
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci		GL_STREAM_READ,		// USAGE_STREAM_READ,
100e5c31af7Sopenharmony_ci		GL_STREAM_COPY,		// USAGE_STREAM_COPY,
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ci		GL_STATIC_READ,		// USAGE_STATIC_READ,
103e5c31af7Sopenharmony_ci		GL_STATIC_COPY,		// USAGE_STATIC_COPY,
104e5c31af7Sopenharmony_ci
105e5c31af7Sopenharmony_ci		GL_DYNAMIC_READ,	// USAGE_DYNAMIC_READ,
106e5c31af7Sopenharmony_ci		GL_DYNAMIC_COPY		// USAGE_DYNAMIC_COPY,
107e5c31af7Sopenharmony_ci	};
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::USAGE_LAST>(usages, (int)usage);
110e5c31af7Sopenharmony_ci}
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_cistatic GLenum inputTypeToGL (DrawTestSpec::InputType type)
113e5c31af7Sopenharmony_ci{
114e5c31af7Sopenharmony_ci	static const GLenum types[] =
115e5c31af7Sopenharmony_ci	{
116e5c31af7Sopenharmony_ci		GL_FLOAT,				// INPUTTYPE_FLOAT = 0,
117e5c31af7Sopenharmony_ci		GL_FIXED,				// INPUTTYPE_FIXED,
118e5c31af7Sopenharmony_ci		GL_DOUBLE,				// INPUTTYPE_DOUBLE
119e5c31af7Sopenharmony_ci		GL_BYTE,				// INPUTTYPE_BYTE,
120e5c31af7Sopenharmony_ci		GL_SHORT,				// INPUTTYPE_SHORT,
121e5c31af7Sopenharmony_ci		GL_UNSIGNED_BYTE,		// INPUTTYPE_UNSIGNED_BYTE,
122e5c31af7Sopenharmony_ci		GL_UNSIGNED_SHORT,		// INPUTTYPE_UNSIGNED_SHORT,
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci		GL_INT,					// INPUTTYPE_INT,
125e5c31af7Sopenharmony_ci		GL_UNSIGNED_INT,		// INPUTTYPE_UNSIGNED_INT,
126e5c31af7Sopenharmony_ci		GL_HALF_FLOAT,			// INPUTTYPE_HALF,
127e5c31af7Sopenharmony_ci		GL_UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
128e5c31af7Sopenharmony_ci		GL_INT_2_10_10_10_REV			// INPUTTYPE_INT_2_10_10_10,
129e5c31af7Sopenharmony_ci	};
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::INPUTTYPE_LAST>(types, (int)type);
132e5c31af7Sopenharmony_ci}
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_cistatic std::string outputTypeToGLType (DrawTestSpec::OutputType type)
135e5c31af7Sopenharmony_ci{
136e5c31af7Sopenharmony_ci	static const char* types[] =
137e5c31af7Sopenharmony_ci	{
138e5c31af7Sopenharmony_ci		"float",		// OUTPUTTYPE_FLOAT = 0,
139e5c31af7Sopenharmony_ci		"vec2",			// OUTPUTTYPE_VEC2,
140e5c31af7Sopenharmony_ci		"vec3",			// OUTPUTTYPE_VEC3,
141e5c31af7Sopenharmony_ci		"vec4",			// OUTPUTTYPE_VEC4,
142e5c31af7Sopenharmony_ci
143e5c31af7Sopenharmony_ci		"int",			// OUTPUTTYPE_INT,
144e5c31af7Sopenharmony_ci		"uint",			// OUTPUTTYPE_UINT,
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ci		"ivec2",		// OUTPUTTYPE_IVEC2,
147e5c31af7Sopenharmony_ci		"ivec3",		// OUTPUTTYPE_IVEC3,
148e5c31af7Sopenharmony_ci		"ivec4",		// OUTPUTTYPE_IVEC4,
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_ci		"uvec2",		// OUTPUTTYPE_UVEC2,
151e5c31af7Sopenharmony_ci		"uvec3",		// OUTPUTTYPE_UVEC3,
152e5c31af7Sopenharmony_ci		"uvec4",		// OUTPUTTYPE_UVEC4,
153e5c31af7Sopenharmony_ci	};
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::OUTPUTTYPE_LAST>(types, (int)type);
156e5c31af7Sopenharmony_ci}
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_cistatic GLenum primitiveToGL (DrawTestSpec::Primitive primitive)
159e5c31af7Sopenharmony_ci{
160e5c31af7Sopenharmony_ci	static const GLenum primitives[] =
161e5c31af7Sopenharmony_ci	{
162e5c31af7Sopenharmony_ci		GL_POINTS,						// PRIMITIVE_POINTS = 0,
163e5c31af7Sopenharmony_ci		GL_TRIANGLES,					// PRIMITIVE_TRIANGLES,
164e5c31af7Sopenharmony_ci		GL_TRIANGLE_FAN,				// PRIMITIVE_TRIANGLE_FAN,
165e5c31af7Sopenharmony_ci		GL_TRIANGLE_STRIP,				// PRIMITIVE_TRIANGLE_STRIP,
166e5c31af7Sopenharmony_ci		GL_LINES,						// PRIMITIVE_LINES
167e5c31af7Sopenharmony_ci		GL_LINE_STRIP,					// PRIMITIVE_LINE_STRIP
168e5c31af7Sopenharmony_ci		GL_LINE_LOOP,					// PRIMITIVE_LINE_LOOP
169e5c31af7Sopenharmony_ci		GL_LINES_ADJACENCY,				// PRIMITIVE_LINES_ADJACENCY
170e5c31af7Sopenharmony_ci		GL_LINE_STRIP_ADJACENCY,		// PRIMITIVE_LINE_STRIP_ADJACENCY
171e5c31af7Sopenharmony_ci		GL_TRIANGLES_ADJACENCY,			// PRIMITIVE_TRIANGLES_ADJACENCY
172e5c31af7Sopenharmony_ci		GL_TRIANGLE_STRIP_ADJACENCY,	// PRIMITIVE_TRIANGLE_STRIP_ADJACENCY
173e5c31af7Sopenharmony_ci	};
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::PRIMITIVE_LAST>(primitives, (int)primitive);
176e5c31af7Sopenharmony_ci}
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_cistatic deUint32 indexTypeToGL (DrawTestSpec::IndexType indexType)
179e5c31af7Sopenharmony_ci{
180e5c31af7Sopenharmony_ci	static const GLenum indexTypes[] =
181e5c31af7Sopenharmony_ci	{
182e5c31af7Sopenharmony_ci		GL_UNSIGNED_BYTE,	// INDEXTYPE_BYTE = 0,
183e5c31af7Sopenharmony_ci		GL_UNSIGNED_SHORT,	// INDEXTYPE_SHORT,
184e5c31af7Sopenharmony_ci		GL_UNSIGNED_INT,	// INDEXTYPE_INT,
185e5c31af7Sopenharmony_ci	};
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::INDEXTYPE_LAST>(indexTypes, (int)indexType);
188e5c31af7Sopenharmony_ci}
189e5c31af7Sopenharmony_ci
190e5c31af7Sopenharmony_cistatic bool inputTypeIsFloatType (DrawTestSpec::InputType type)
191e5c31af7Sopenharmony_ci{
192e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::INPUTTYPE_FLOAT)
193e5c31af7Sopenharmony_ci		return true;
194e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::INPUTTYPE_FIXED)
195e5c31af7Sopenharmony_ci		return true;
196e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::INPUTTYPE_HALF)
197e5c31af7Sopenharmony_ci		return true;
198e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::INPUTTYPE_DOUBLE)
199e5c31af7Sopenharmony_ci		return true;
200e5c31af7Sopenharmony_ci	return false;
201e5c31af7Sopenharmony_ci}
202e5c31af7Sopenharmony_ci
203e5c31af7Sopenharmony_cistatic bool outputTypeIsFloatType (DrawTestSpec::OutputType type)
204e5c31af7Sopenharmony_ci{
205e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::OUTPUTTYPE_FLOAT
206e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_VEC2
207e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_VEC3
208e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_VEC4)
209e5c31af7Sopenharmony_ci		return true;
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci	return false;
212e5c31af7Sopenharmony_ci}
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_cistatic bool outputTypeIsIntType (DrawTestSpec::OutputType type)
215e5c31af7Sopenharmony_ci{
216e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::OUTPUTTYPE_INT
217e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_IVEC2
218e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_IVEC3
219e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_IVEC4)
220e5c31af7Sopenharmony_ci		return true;
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ci	return false;
223e5c31af7Sopenharmony_ci}
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_cistatic bool outputTypeIsUintType (DrawTestSpec::OutputType type)
226e5c31af7Sopenharmony_ci{
227e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::OUTPUTTYPE_UINT
228e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_UVEC2
229e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_UVEC3
230e5c31af7Sopenharmony_ci		|| type == DrawTestSpec::OUTPUTTYPE_UVEC4)
231e5c31af7Sopenharmony_ci		return true;
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci	return false;
234e5c31af7Sopenharmony_ci}
235e5c31af7Sopenharmony_ci
236e5c31af7Sopenharmony_cistatic size_t getElementCount (DrawTestSpec::Primitive primitive, size_t primitiveCount)
237e5c31af7Sopenharmony_ci{
238e5c31af7Sopenharmony_ci	switch (primitive)
239e5c31af7Sopenharmony_ci	{
240e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_POINTS:						return primitiveCount;
241e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES:						return primitiveCount * 3;
242e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:					return primitiveCount + 2;
243e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:				return primitiveCount + 2;
244e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES:							return primitiveCount * 2;
245e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP:					return primitiveCount + 1;
246e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_LOOP:						return (primitiveCount==1) ? (2) : (primitiveCount);
247e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:				return primitiveCount * 4;
248e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:			return primitiveCount + 3;
249e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:			return primitiveCount * 6;
250e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:		return primitiveCount * 2 + 4;
251e5c31af7Sopenharmony_ci		default:
252e5c31af7Sopenharmony_ci			DE_ASSERT(false);
253e5c31af7Sopenharmony_ci			return 0;
254e5c31af7Sopenharmony_ci	}
255e5c31af7Sopenharmony_ci}
256e5c31af7Sopenharmony_ci
257e5c31af7Sopenharmony_cistruct MethodInfo
258e5c31af7Sopenharmony_ci{
259e5c31af7Sopenharmony_ci	bool indexed;
260e5c31af7Sopenharmony_ci	bool instanced;
261e5c31af7Sopenharmony_ci	bool ranged;
262e5c31af7Sopenharmony_ci	bool first;
263e5c31af7Sopenharmony_ci	bool baseVertex;
264e5c31af7Sopenharmony_ci	bool indirect;
265e5c31af7Sopenharmony_ci};
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_cistatic MethodInfo getMethodInfo (gls::DrawTestSpec::DrawMethod method)
268e5c31af7Sopenharmony_ci{
269e5c31af7Sopenharmony_ci	static const MethodInfo infos[] =
270e5c31af7Sopenharmony_ci	{
271e5c31af7Sopenharmony_ci		//	indexed		instanced	ranged		first		baseVertex	indirect
272e5c31af7Sopenharmony_ci		{	false,		false,		false,		true,		false,		false	}, //!< DRAWMETHOD_DRAWARRAYS,
273e5c31af7Sopenharmony_ci		{	false,		true,		false,		true,		false,		false	}, //!< DRAWMETHOD_DRAWARRAYS_INSTANCED,
274e5c31af7Sopenharmony_ci		{	false,		true,		false,		true,		false,		true	}, //!< DRAWMETHOD_DRAWARRAYS_INDIRECT,
275e5c31af7Sopenharmony_ci		{	true,		false,		false,		false,		false,		false	}, //!< DRAWMETHOD_DRAWELEMENTS,
276e5c31af7Sopenharmony_ci		{	true,		false,		true,		false,		false,		false	}, //!< DRAWMETHOD_DRAWELEMENTS_RANGED,
277e5c31af7Sopenharmony_ci		{	true,		true,		false,		false,		false,		false	}, //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED,
278e5c31af7Sopenharmony_ci		{	true,		true,		false,		false,		true,		true	}, //!< DRAWMETHOD_DRAWELEMENTS_INDIRECT,
279e5c31af7Sopenharmony_ci		{	true,		false,		false,		false,		true,		false	}, //!< DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
280e5c31af7Sopenharmony_ci		{	true,		true,		false,		false,		true,		false	}, //!< DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
281e5c31af7Sopenharmony_ci		{	true,		false,		true,		false,		true,		false	}, //!< DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
282e5c31af7Sopenharmony_ci	};
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::DRAWMETHOD_LAST>(infos, (int)method);
285e5c31af7Sopenharmony_ci}
286e5c31af7Sopenharmony_ci
287e5c31af7Sopenharmony_citemplate<class T>
288e5c31af7Sopenharmony_ciinline static void alignmentSafeAssignment (char* dst, T val)
289e5c31af7Sopenharmony_ci{
290e5c31af7Sopenharmony_ci	std::memcpy(dst, &val, sizeof(T));
291e5c31af7Sopenharmony_ci}
292e5c31af7Sopenharmony_ci
293e5c31af7Sopenharmony_cistatic bool checkSpecsShaderCompatible (const DrawTestSpec& a, const DrawTestSpec& b)
294e5c31af7Sopenharmony_ci{
295e5c31af7Sopenharmony_ci	// Only the attributes matter
296e5c31af7Sopenharmony_ci	if (a.attribs.size() != b.attribs.size())
297e5c31af7Sopenharmony_ci		return false;
298e5c31af7Sopenharmony_ci
299e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < a.attribs.size(); ++ndx)
300e5c31af7Sopenharmony_ci	{
301e5c31af7Sopenharmony_ci		// Only the output type (== shader input type) matters and the usage in the shader.
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci		if (a.attribs[ndx].additionalPositionAttribute != b.attribs[ndx].additionalPositionAttribute)
304e5c31af7Sopenharmony_ci			return false;
305e5c31af7Sopenharmony_ci
306e5c31af7Sopenharmony_ci		// component counts need not to match
307e5c31af7Sopenharmony_ci		if (outputTypeIsFloatType(a.attribs[ndx].outputType) && outputTypeIsFloatType(b.attribs[ndx].outputType))
308e5c31af7Sopenharmony_ci			continue;
309e5c31af7Sopenharmony_ci		if (outputTypeIsIntType(a.attribs[ndx].outputType) && outputTypeIsIntType(b.attribs[ndx].outputType))
310e5c31af7Sopenharmony_ci			continue;
311e5c31af7Sopenharmony_ci		if (outputTypeIsUintType(a.attribs[ndx].outputType) && outputTypeIsUintType(b.attribs[ndx].outputType))
312e5c31af7Sopenharmony_ci			continue;
313e5c31af7Sopenharmony_ci
314e5c31af7Sopenharmony_ci		return false;
315e5c31af7Sopenharmony_ci	}
316e5c31af7Sopenharmony_ci
317e5c31af7Sopenharmony_ci	return true;
318e5c31af7Sopenharmony_ci}
319e5c31af7Sopenharmony_ci
320e5c31af7Sopenharmony_ci// generate random vectors in a way that does not depend on argument evaluation order
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_citcu::Vec4 generateRandomVec4 (de::Random& random)
323e5c31af7Sopenharmony_ci{
324e5c31af7Sopenharmony_ci	tcu::Vec4 retVal;
325e5c31af7Sopenharmony_ci
326e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; ++i)
327e5c31af7Sopenharmony_ci		retVal[i] = random.getFloat();
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci	return retVal;
330e5c31af7Sopenharmony_ci}
331e5c31af7Sopenharmony_ci
332e5c31af7Sopenharmony_citcu::IVec4 generateRandomIVec4 (de::Random& random)
333e5c31af7Sopenharmony_ci{
334e5c31af7Sopenharmony_ci	tcu::IVec4 retVal;
335e5c31af7Sopenharmony_ci
336e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; ++i)
337e5c31af7Sopenharmony_ci		retVal[i] = random.getUint32();
338e5c31af7Sopenharmony_ci
339e5c31af7Sopenharmony_ci	return retVal;
340e5c31af7Sopenharmony_ci}
341e5c31af7Sopenharmony_ci
342e5c31af7Sopenharmony_citcu::UVec4 generateRandomUVec4 (de::Random& random)
343e5c31af7Sopenharmony_ci{
344e5c31af7Sopenharmony_ci	tcu::UVec4 retVal;
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; ++i)
347e5c31af7Sopenharmony_ci		retVal[i] = random.getUint32();
348e5c31af7Sopenharmony_ci
349e5c31af7Sopenharmony_ci	return retVal;
350e5c31af7Sopenharmony_ci}
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci// IterationLogSectionEmitter
353e5c31af7Sopenharmony_ci
354e5c31af7Sopenharmony_ciclass IterationLogSectionEmitter
355e5c31af7Sopenharmony_ci{
356e5c31af7Sopenharmony_cipublic:
357e5c31af7Sopenharmony_ci								IterationLogSectionEmitter		(tcu::TestLog& log, size_t testIteration, size_t testIterations, const std::string& description, bool enabled);
358e5c31af7Sopenharmony_ci								~IterationLogSectionEmitter		(void);
359e5c31af7Sopenharmony_ciprivate:
360e5c31af7Sopenharmony_ci								IterationLogSectionEmitter		(const IterationLogSectionEmitter&); // delete
361e5c31af7Sopenharmony_ci	IterationLogSectionEmitter&	operator=						(const IterationLogSectionEmitter&); // delete
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ci	tcu::TestLog&				m_log;
364e5c31af7Sopenharmony_ci	bool						m_enabled;
365e5c31af7Sopenharmony_ci};
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ciIterationLogSectionEmitter::IterationLogSectionEmitter (tcu::TestLog& log, size_t testIteration, size_t testIterations, const std::string& description, bool enabled)
368e5c31af7Sopenharmony_ci	: m_log		(log)
369e5c31af7Sopenharmony_ci	, m_enabled	(enabled)
370e5c31af7Sopenharmony_ci{
371e5c31af7Sopenharmony_ci	if (m_enabled)
372e5c31af7Sopenharmony_ci	{
373e5c31af7Sopenharmony_ci		std::ostringstream buf;
374e5c31af7Sopenharmony_ci		buf << "Iteration " << (testIteration+1) << "/" << testIterations;
375e5c31af7Sopenharmony_ci
376e5c31af7Sopenharmony_ci		if (!description.empty())
377e5c31af7Sopenharmony_ci			buf << " - " << description;
378e5c31af7Sopenharmony_ci
379e5c31af7Sopenharmony_ci		m_log << tcu::TestLog::Section(buf.str(), buf.str());
380e5c31af7Sopenharmony_ci	}
381e5c31af7Sopenharmony_ci}
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ciIterationLogSectionEmitter::~IterationLogSectionEmitter (void)
384e5c31af7Sopenharmony_ci{
385e5c31af7Sopenharmony_ci	if (m_enabled)
386e5c31af7Sopenharmony_ci		m_log << tcu::TestLog::EndSection;
387e5c31af7Sopenharmony_ci}
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci// GLValue
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ciclass GLValue
392e5c31af7Sopenharmony_ci{
393e5c31af7Sopenharmony_cipublic:
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_ci	template<class Type>
396e5c31af7Sopenharmony_ci	class WrappedType
397e5c31af7Sopenharmony_ci	{
398e5c31af7Sopenharmony_ci	public:
399e5c31af7Sopenharmony_ci		static WrappedType<Type>	create			(Type value)							{ WrappedType<Type> v; v.m_value = value; return v; }
400e5c31af7Sopenharmony_ci		inline Type					getValue		(void) const							{ return m_value; }
401e5c31af7Sopenharmony_ci
402e5c31af7Sopenharmony_ci		inline WrappedType<Type>	operator+		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create((Type)(m_value + other.getValue())); }
403e5c31af7Sopenharmony_ci		inline WrappedType<Type>	operator*		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create((Type)(m_value * other.getValue())); }
404e5c31af7Sopenharmony_ci		inline WrappedType<Type>	operator/		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create((Type)(m_value / other.getValue())); }
405e5c31af7Sopenharmony_ci		inline WrappedType<Type>	operator-		(const WrappedType<Type>& other) const	{ return WrappedType<Type>::create((Type)(m_value - other.getValue())); }
406e5c31af7Sopenharmony_ci
407e5c31af7Sopenharmony_ci		inline WrappedType<Type>&	operator+=		(const WrappedType<Type>& other)		{ m_value += other.getValue(); return *this; }
408e5c31af7Sopenharmony_ci		inline WrappedType<Type>&	operator*=		(const WrappedType<Type>& other)		{ m_value *= other.getValue(); return *this; }
409e5c31af7Sopenharmony_ci		inline WrappedType<Type>&	operator/=		(const WrappedType<Type>& other)		{ m_value /= other.getValue(); return *this; }
410e5c31af7Sopenharmony_ci		inline WrappedType<Type>&	operator-=		(const WrappedType<Type>& other)		{ m_value -= other.getValue(); return *this; }
411e5c31af7Sopenharmony_ci
412e5c31af7Sopenharmony_ci		inline bool					operator==		(const WrappedType<Type>& other) const	{ return m_value == other.m_value; }
413e5c31af7Sopenharmony_ci		inline bool					operator!=		(const WrappedType<Type>& other) const	{ return m_value != other.m_value; }
414e5c31af7Sopenharmony_ci		inline bool					operator<		(const WrappedType<Type>& other) const	{ return m_value < other.m_value; }
415e5c31af7Sopenharmony_ci		inline bool					operator>		(const WrappedType<Type>& other) const	{ return m_value > other.m_value; }
416e5c31af7Sopenharmony_ci		inline bool					operator<=		(const WrappedType<Type>& other) const	{ return m_value <= other.m_value; }
417e5c31af7Sopenharmony_ci		inline bool					operator>=		(const WrappedType<Type>& other) const	{ return m_value >= other.m_value; }
418e5c31af7Sopenharmony_ci
419e5c31af7Sopenharmony_ci		inline						operator Type	(void) const							{ return m_value; }
420e5c31af7Sopenharmony_ci		template<class T>
421e5c31af7Sopenharmony_ci		inline T					to				(void) const							{ return (T)m_value; }
422e5c31af7Sopenharmony_ci	private:
423e5c31af7Sopenharmony_ci		Type	m_value;
424e5c31af7Sopenharmony_ci	};
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci	typedef WrappedType<deInt16>	Short;
427e5c31af7Sopenharmony_ci	typedef WrappedType<deUint16>	Ushort;
428e5c31af7Sopenharmony_ci
429e5c31af7Sopenharmony_ci	typedef WrappedType<deInt8>		Byte;
430e5c31af7Sopenharmony_ci	typedef WrappedType<deUint8>	Ubyte;
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_ci	typedef WrappedType<float>		Float;
433e5c31af7Sopenharmony_ci	typedef WrappedType<double>		Double;
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ci	typedef WrappedType<deUint32>	Uint;
436e5c31af7Sopenharmony_ci
437e5c31af7Sopenharmony_ci	// All operations are calculated using 64bit values to avoid signed integer overflow which is undefined.
438e5c31af7Sopenharmony_ci	class Int
439e5c31af7Sopenharmony_ci	{
440e5c31af7Sopenharmony_ci	public:
441e5c31af7Sopenharmony_ci		static Int		create				(deInt32 value)				{ Int v; v.m_value = value; return v; }
442e5c31af7Sopenharmony_ci		inline deInt32	getValue			(void) const				{ return m_value; }
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci		inline Int		operator+			(const Int& other) const	{ return Int::create((deInt32)((deInt64)m_value + (deInt64)other.getValue())); }
445e5c31af7Sopenharmony_ci		inline Int		operator*			(const Int& other) const	{ return Int::create((deInt32)((deInt64)m_value * (deInt64)other.getValue())); }
446e5c31af7Sopenharmony_ci		inline Int		operator/			(const Int& other) const	{ return Int::create((deInt32)((deInt64)m_value / (deInt64)other.getValue())); }
447e5c31af7Sopenharmony_ci		inline Int		operator-			(const Int& other) const	{ return Int::create((deInt32)((deInt64)m_value - (deInt64)other.getValue())); }
448e5c31af7Sopenharmony_ci
449e5c31af7Sopenharmony_ci		inline Int&		operator+=			(const Int& other)			{ m_value = (deInt32)((deInt64)m_value + (deInt64)other.getValue()); return *this; }
450e5c31af7Sopenharmony_ci		inline Int&		operator*=			(const Int& other)			{ m_value = (deInt32)((deInt64)m_value * (deInt64)other.getValue()); return *this; }
451e5c31af7Sopenharmony_ci		inline Int&		operator/=			(const Int& other)			{ m_value = (deInt32)((deInt64)m_value / (deInt64)other.getValue()); return *this; }
452e5c31af7Sopenharmony_ci		inline Int&		operator-=			(const Int& other)			{ m_value = (deInt32)((deInt64)m_value - (deInt64)other.getValue()); return *this; }
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci		inline bool		operator==			(const Int& other) const	{ return m_value == other.m_value; }
455e5c31af7Sopenharmony_ci		inline bool		operator!=			(const Int& other) const	{ return m_value != other.m_value; }
456e5c31af7Sopenharmony_ci		inline bool		operator<			(const Int& other) const	{ return m_value < other.m_value; }
457e5c31af7Sopenharmony_ci		inline bool		operator>			(const Int& other) const	{ return m_value > other.m_value; }
458e5c31af7Sopenharmony_ci		inline bool		operator<=			(const Int& other) const	{ return m_value <= other.m_value; }
459e5c31af7Sopenharmony_ci		inline bool		operator>=			(const Int& other) const	{ return m_value >= other.m_value; }
460e5c31af7Sopenharmony_ci
461e5c31af7Sopenharmony_ci		inline			operator deInt32	(void) const				{ return m_value; }
462e5c31af7Sopenharmony_ci		template<class T>
463e5c31af7Sopenharmony_ci		inline T		to					(void) const				{ return (T)m_value; }
464e5c31af7Sopenharmony_ci	private:
465e5c31af7Sopenharmony_ci		deInt32	m_value;
466e5c31af7Sopenharmony_ci	};
467e5c31af7Sopenharmony_ci
468e5c31af7Sopenharmony_ci	class Half
469e5c31af7Sopenharmony_ci	{
470e5c31af7Sopenharmony_ci	public:
471e5c31af7Sopenharmony_ci		static Half			create			(float value)				{ Half h; h.m_value = floatToHalf(value); return h; }
472e5c31af7Sopenharmony_ci		inline deFloat16	getValue		(void) const				{ return m_value; }
473e5c31af7Sopenharmony_ci
474e5c31af7Sopenharmony_ci		inline Half			operator+		(const Half& other) const	{ return create(halfToFloat(m_value) + halfToFloat(other.getValue())); }
475e5c31af7Sopenharmony_ci		inline Half			operator*		(const Half& other) const	{ return create(halfToFloat(m_value) * halfToFloat(other.getValue())); }
476e5c31af7Sopenharmony_ci		inline Half			operator/		(const Half& other) const	{ return create(halfToFloat(m_value) / halfToFloat(other.getValue())); }
477e5c31af7Sopenharmony_ci		inline Half			operator-		(const Half& other) const	{ return create(halfToFloat(m_value) - halfToFloat(other.getValue())); }
478e5c31af7Sopenharmony_ci
479e5c31af7Sopenharmony_ci		inline Half&		operator+=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) + halfToFloat(m_value)); return *this; }
480e5c31af7Sopenharmony_ci		inline Half&		operator*=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) * halfToFloat(m_value)); return *this; }
481e5c31af7Sopenharmony_ci		inline Half&		operator/=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) / halfToFloat(m_value)); return *this; }
482e5c31af7Sopenharmony_ci		inline Half&		operator-=		(const Half& other)			{ m_value = floatToHalf(halfToFloat(other.getValue()) - halfToFloat(m_value)); return *this; }
483e5c31af7Sopenharmony_ci
484e5c31af7Sopenharmony_ci		inline bool			operator==		(const Half& other) const	{ return m_value == other.m_value; }
485e5c31af7Sopenharmony_ci		inline bool			operator!=		(const Half& other) const	{ return m_value != other.m_value; }
486e5c31af7Sopenharmony_ci		inline bool			operator<		(const Half& other) const	{ return halfToFloat(m_value) < halfToFloat(other.m_value); }
487e5c31af7Sopenharmony_ci		inline bool			operator>		(const Half& other) const	{ return halfToFloat(m_value) > halfToFloat(other.m_value); }
488e5c31af7Sopenharmony_ci		inline bool			operator<=		(const Half& other) const	{ return halfToFloat(m_value) <= halfToFloat(other.m_value); }
489e5c31af7Sopenharmony_ci		inline bool			operator>=		(const Half& other) const	{ return halfToFloat(m_value) >= halfToFloat(other.m_value); }
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci		template<class T>
492e5c31af7Sopenharmony_ci		inline T			to				(void) const				{ return (T)halfToFloat(m_value); }
493e5c31af7Sopenharmony_ci
494e5c31af7Sopenharmony_ci		inline static deFloat16	floatToHalf		(float f);
495e5c31af7Sopenharmony_ci		inline static float		halfToFloat		(deFloat16 h);
496e5c31af7Sopenharmony_ci	private:
497e5c31af7Sopenharmony_ci		deFloat16 m_value;
498e5c31af7Sopenharmony_ci	};
499e5c31af7Sopenharmony_ci
500e5c31af7Sopenharmony_ci	class Fixed
501e5c31af7Sopenharmony_ci	{
502e5c31af7Sopenharmony_ci	public:
503e5c31af7Sopenharmony_ci		static Fixed		create			(deInt32 value)				{ Fixed v; v.m_value = value; return v; }
504e5c31af7Sopenharmony_ci		inline deInt32		getValue		(void) const				{ return m_value; }
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci		inline Fixed		operator+		(const Fixed& other) const	{ return create(m_value + other.getValue()); }
507e5c31af7Sopenharmony_ci		inline Fixed		operator*		(const Fixed& other) const	{ return create(m_value * other.getValue()); }
508e5c31af7Sopenharmony_ci		inline Fixed		operator/		(const Fixed& other) const	{ return create(m_value / other.getValue()); }
509e5c31af7Sopenharmony_ci		inline Fixed		operator-		(const Fixed& other) const	{ return create(m_value - other.getValue()); }
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci		inline Fixed&		operator+=		(const Fixed& other)		{ m_value += other.getValue(); return *this; }
512e5c31af7Sopenharmony_ci		inline Fixed&		operator*=		(const Fixed& other)		{ m_value *= other.getValue(); return *this; }
513e5c31af7Sopenharmony_ci		inline Fixed&		operator/=		(const Fixed& other)		{ m_value /= other.getValue(); return *this; }
514e5c31af7Sopenharmony_ci		inline Fixed&		operator-=		(const Fixed& other)		{ m_value -= other.getValue(); return *this; }
515e5c31af7Sopenharmony_ci
516e5c31af7Sopenharmony_ci		inline bool			operator==		(const Fixed& other) const	{ return m_value == other.m_value; }
517e5c31af7Sopenharmony_ci		inline bool			operator!=		(const Fixed& other) const	{ return m_value != other.m_value; }
518e5c31af7Sopenharmony_ci		inline bool			operator<		(const Fixed& other) const	{ return m_value < other.m_value; }
519e5c31af7Sopenharmony_ci		inline bool			operator>		(const Fixed& other) const	{ return m_value > other.m_value; }
520e5c31af7Sopenharmony_ci		inline bool			operator<=		(const Fixed& other) const	{ return m_value <= other.m_value; }
521e5c31af7Sopenharmony_ci		inline bool			operator>=		(const Fixed& other) const	{ return m_value >= other.m_value; }
522e5c31af7Sopenharmony_ci
523e5c31af7Sopenharmony_ci		inline				operator deInt32 (void) const				{ return m_value; }
524e5c31af7Sopenharmony_ci		template<class T>
525e5c31af7Sopenharmony_ci		inline T			to				(void) const				{ return (T)m_value; }
526e5c31af7Sopenharmony_ci	private:
527e5c31af7Sopenharmony_ci		deInt32				m_value;
528e5c31af7Sopenharmony_ci	};
529e5c31af7Sopenharmony_ci
530e5c31af7Sopenharmony_ci	// \todo [mika] This is pretty messy
531e5c31af7Sopenharmony_ci						GLValue			(void)			: type(DrawTestSpec::INPUTTYPE_LAST) {}
532e5c31af7Sopenharmony_ci	explicit			GLValue			(Float value)	: type(DrawTestSpec::INPUTTYPE_FLOAT),				fl(value)	{}
533e5c31af7Sopenharmony_ci	explicit			GLValue			(Fixed value)	: type(DrawTestSpec::INPUTTYPE_FIXED),				fi(value)	{}
534e5c31af7Sopenharmony_ci	explicit			GLValue			(Byte value)	: type(DrawTestSpec::INPUTTYPE_BYTE),				b(value)	{}
535e5c31af7Sopenharmony_ci	explicit			GLValue			(Ubyte value)	: type(DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE),		ub(value)	{}
536e5c31af7Sopenharmony_ci	explicit			GLValue			(Short value)	: type(DrawTestSpec::INPUTTYPE_SHORT),				s(value)	{}
537e5c31af7Sopenharmony_ci	explicit			GLValue			(Ushort value)	: type(DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT),		us(value)	{}
538e5c31af7Sopenharmony_ci	explicit			GLValue			(Int value)		: type(DrawTestSpec::INPUTTYPE_INT),				i(value)	{}
539e5c31af7Sopenharmony_ci	explicit			GLValue			(Uint value)	: type(DrawTestSpec::INPUTTYPE_UNSIGNED_INT),		ui(value)	{}
540e5c31af7Sopenharmony_ci	explicit			GLValue			(Half value)	: type(DrawTestSpec::INPUTTYPE_HALF),				h(value)	{}
541e5c31af7Sopenharmony_ci	explicit			GLValue			(Double value)	: type(DrawTestSpec::INPUTTYPE_DOUBLE),				d(value)	{}
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_ci	float				toFloat			(void) const;
544e5c31af7Sopenharmony_ci
545e5c31af7Sopenharmony_ci	static GLValue		getMaxValue		(DrawTestSpec::InputType type);
546e5c31af7Sopenharmony_ci	static GLValue		getMinValue		(DrawTestSpec::InputType type);
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci	DrawTestSpec::InputType	type;
549e5c31af7Sopenharmony_ci
550e5c31af7Sopenharmony_ci	union
551e5c31af7Sopenharmony_ci	{
552e5c31af7Sopenharmony_ci		Float		fl;
553e5c31af7Sopenharmony_ci		Fixed		fi;
554e5c31af7Sopenharmony_ci		Double		d;
555e5c31af7Sopenharmony_ci		Byte		b;
556e5c31af7Sopenharmony_ci		Ubyte		ub;
557e5c31af7Sopenharmony_ci		Short		s;
558e5c31af7Sopenharmony_ci		Ushort		us;
559e5c31af7Sopenharmony_ci		Int			i;
560e5c31af7Sopenharmony_ci		Uint		ui;
561e5c31af7Sopenharmony_ci		Half		h;
562e5c31af7Sopenharmony_ci	};
563e5c31af7Sopenharmony_ci};
564e5c31af7Sopenharmony_ci
565e5c31af7Sopenharmony_ciinline deFloat16 GLValue::Half::floatToHalf (float f)
566e5c31af7Sopenharmony_ci{
567e5c31af7Sopenharmony_ci	// No denorm support.
568e5c31af7Sopenharmony_ci	tcu::Float<deUint16, 5, 10, 15, tcu::FLOAT_HAS_SIGN> v(f);
569e5c31af7Sopenharmony_ci	DE_ASSERT(!v.isNaN() && !v.isInf());
570e5c31af7Sopenharmony_ci	return v.bits();
571e5c31af7Sopenharmony_ci}
572e5c31af7Sopenharmony_ci
573e5c31af7Sopenharmony_ciinline float GLValue::Half::halfToFloat (deFloat16 h)
574e5c31af7Sopenharmony_ci{
575e5c31af7Sopenharmony_ci	return tcu::Float16((deUint16)h).asFloat();
576e5c31af7Sopenharmony_ci}
577e5c31af7Sopenharmony_ci
578e5c31af7Sopenharmony_cifloat GLValue::toFloat (void) const
579e5c31af7Sopenharmony_ci{
580e5c31af7Sopenharmony_ci	switch (type)
581e5c31af7Sopenharmony_ci	{
582e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_FLOAT:
583e5c31af7Sopenharmony_ci			return fl.getValue();
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_BYTE:
586e5c31af7Sopenharmony_ci			return b.getValue();
587e5c31af7Sopenharmony_ci
588e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE:
589e5c31af7Sopenharmony_ci			return ub.getValue();
590e5c31af7Sopenharmony_ci
591e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_SHORT:
592e5c31af7Sopenharmony_ci			return s.getValue();
593e5c31af7Sopenharmony_ci
594e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT:
595e5c31af7Sopenharmony_ci			return us.getValue();
596e5c31af7Sopenharmony_ci
597e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_FIXED:
598e5c31af7Sopenharmony_ci		{
599e5c31af7Sopenharmony_ci			int maxValue = 65536;
600e5c31af7Sopenharmony_ci			return (float)(double(2 * fi.getValue() + 1) / (maxValue - 1));
601e5c31af7Sopenharmony_ci		}
602e5c31af7Sopenharmony_ci
603e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_UNSIGNED_INT:
604e5c31af7Sopenharmony_ci			return (float)ui.getValue();
605e5c31af7Sopenharmony_ci
606e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_INT:
607e5c31af7Sopenharmony_ci			return (float)i.getValue();
608e5c31af7Sopenharmony_ci
609e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_HALF:
610e5c31af7Sopenharmony_ci			return h.to<float>();
611e5c31af7Sopenharmony_ci
612e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_DOUBLE:
613e5c31af7Sopenharmony_ci			return d.to<float>();
614e5c31af7Sopenharmony_ci
615e5c31af7Sopenharmony_ci		default:
616e5c31af7Sopenharmony_ci			DE_ASSERT(false);
617e5c31af7Sopenharmony_ci			return 0.0f;
618e5c31af7Sopenharmony_ci	}
619e5c31af7Sopenharmony_ci}
620e5c31af7Sopenharmony_ci
621e5c31af7Sopenharmony_ciGLValue GLValue::getMaxValue (DrawTestSpec::InputType type)
622e5c31af7Sopenharmony_ci{
623e5c31af7Sopenharmony_ci	GLValue rangesHi[(int)DrawTestSpec::INPUTTYPE_LAST];
624e5c31af7Sopenharmony_ci
625e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_FLOAT]			= GLValue(Float::create(127.0f));
626e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_DOUBLE]			= GLValue(Double::create(127.0f));
627e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_BYTE]				= GLValue(Byte::create(127));
628e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE]	= GLValue(Ubyte::create(255));
629e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT]	= GLValue(Ushort::create(65530));
630e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_SHORT]			= GLValue(Short::create(32760));
631e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_FIXED]			= GLValue(Fixed::create(32760));
632e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_INT]				= GLValue(Int::create(2147483647));
633e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_INT]		= GLValue(Uint::create(4294967295u));
634e5c31af7Sopenharmony_ci	rangesHi[(int)DrawTestSpec::INPUTTYPE_HALF]				= GLValue(Half::create(256.0f));
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_ci	return rangesHi[(int)type];
637e5c31af7Sopenharmony_ci}
638e5c31af7Sopenharmony_ci
639e5c31af7Sopenharmony_ciGLValue GLValue::getMinValue (DrawTestSpec::InputType type)
640e5c31af7Sopenharmony_ci{
641e5c31af7Sopenharmony_ci	GLValue rangesLo[(int)DrawTestSpec::INPUTTYPE_LAST];
642e5c31af7Sopenharmony_ci
643e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_FLOAT]			= GLValue(Float::create(-127.0f));
644e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_DOUBLE]			= GLValue(Double::create(-127.0f));
645e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_BYTE]				= GLValue(Byte::create(-127));
646e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE]	= GLValue(Ubyte::create(0));
647e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT]	= GLValue(Ushort::create(0));
648e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_SHORT]			= GLValue(Short::create(-32760));
649e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_FIXED]			= GLValue(Fixed::create(-32760));
650e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_INT]				= GLValue(Int::create(-2147483647));
651e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_UNSIGNED_INT]		= GLValue(Uint::create(0));
652e5c31af7Sopenharmony_ci	rangesLo[(int)DrawTestSpec::INPUTTYPE_HALF]				= GLValue(Half::create(-256.0f));
653e5c31af7Sopenharmony_ci
654e5c31af7Sopenharmony_ci	return rangesLo[(int)type];
655e5c31af7Sopenharmony_ci}
656e5c31af7Sopenharmony_ci
657e5c31af7Sopenharmony_citemplate<typename T>
658e5c31af7Sopenharmony_cistruct GLValueTypeTraits;
659e5c31af7Sopenharmony_ci
660e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Float>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_FLOAT;			};
661e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Double> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_DOUBLE;			};
662e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Byte>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_BYTE;			};
663e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Ubyte>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE;	};
664e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Ushort> { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT;	};
665e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Short>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_SHORT;			};
666e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Fixed>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_FIXED;			};
667e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Int>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_INT;			};
668e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Uint>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_UNSIGNED_INT;	};
669e5c31af7Sopenharmony_citemplate<> struct GLValueTypeTraits<GLValue::Half>	 { static const DrawTestSpec::InputType Type = DrawTestSpec::INPUTTYPE_HALF;			};
670e5c31af7Sopenharmony_ci
671e5c31af7Sopenharmony_citemplate<typename T>
672e5c31af7Sopenharmony_ciinline T extractGLValue (const GLValue& v);
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_citemplate<> GLValue::Float	inline extractGLValue<GLValue::Float>		(const GLValue& v) { return v.fl; }
675e5c31af7Sopenharmony_citemplate<> GLValue::Double	inline extractGLValue<GLValue::Double>		(const GLValue& v) { return v.d; }
676e5c31af7Sopenharmony_citemplate<> GLValue::Byte	inline extractGLValue<GLValue::Byte>		(const GLValue& v) { return v.b; }
677e5c31af7Sopenharmony_citemplate<> GLValue::Ubyte	inline extractGLValue<GLValue::Ubyte>		(const GLValue& v) { return v.ub; }
678e5c31af7Sopenharmony_citemplate<> GLValue::Ushort	inline extractGLValue<GLValue::Ushort>		(const GLValue& v) { return v.us; }
679e5c31af7Sopenharmony_citemplate<> GLValue::Short	inline extractGLValue<GLValue::Short>		(const GLValue& v) { return v.s; }
680e5c31af7Sopenharmony_citemplate<> GLValue::Fixed	inline extractGLValue<GLValue::Fixed>		(const GLValue& v) { return v.fi; }
681e5c31af7Sopenharmony_citemplate<> GLValue::Int		inline extractGLValue<GLValue::Int>			(const GLValue& v) { return v.i; }
682e5c31af7Sopenharmony_citemplate<> GLValue::Uint	inline extractGLValue<GLValue::Uint>		(const GLValue& v) { return v.ui; }
683e5c31af7Sopenharmony_citemplate<> GLValue::Half	inline extractGLValue<GLValue::Half>		(const GLValue& v) { return v.h; }
684e5c31af7Sopenharmony_ci
685e5c31af7Sopenharmony_citemplate<class T>
686e5c31af7Sopenharmony_ciinline T getRandom (deRandom& rnd, T min, T max);
687e5c31af7Sopenharmony_ci
688e5c31af7Sopenharmony_citemplate<>
689e5c31af7Sopenharmony_ciinline GLValue::Float getRandom (deRandom& rnd, GLValue::Float min, GLValue::Float max)
690e5c31af7Sopenharmony_ci{
691e5c31af7Sopenharmony_ci	if (max < min)
692e5c31af7Sopenharmony_ci		return min;
693e5c31af7Sopenharmony_ci
694e5c31af7Sopenharmony_ci	return GLValue::Float::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
695e5c31af7Sopenharmony_ci}
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_citemplate<>
698e5c31af7Sopenharmony_ciinline GLValue::Double getRandom (deRandom& rnd, GLValue::Double min, GLValue::Double max)
699e5c31af7Sopenharmony_ci{
700e5c31af7Sopenharmony_ci	if (max < min)
701e5c31af7Sopenharmony_ci		return min;
702e5c31af7Sopenharmony_ci
703e5c31af7Sopenharmony_ci	return GLValue::Double::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
704e5c31af7Sopenharmony_ci}
705e5c31af7Sopenharmony_ci
706e5c31af7Sopenharmony_citemplate<>
707e5c31af7Sopenharmony_ciinline GLValue::Short getRandom (deRandom& rnd, GLValue::Short min, GLValue::Short max)
708e5c31af7Sopenharmony_ci{
709e5c31af7Sopenharmony_ci	if (max < min)
710e5c31af7Sopenharmony_ci		return min;
711e5c31af7Sopenharmony_ci
712e5c31af7Sopenharmony_ci	return GLValue::Short::create((min == max ? min : (deInt16)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
713e5c31af7Sopenharmony_ci}
714e5c31af7Sopenharmony_ci
715e5c31af7Sopenharmony_citemplate<>
716e5c31af7Sopenharmony_ciinline GLValue::Ushort getRandom (deRandom& rnd, GLValue::Ushort min, GLValue::Ushort max)
717e5c31af7Sopenharmony_ci{
718e5c31af7Sopenharmony_ci	if (max < min)
719e5c31af7Sopenharmony_ci		return min;
720e5c31af7Sopenharmony_ci
721e5c31af7Sopenharmony_ci	return GLValue::Ushort::create((min == max ? min : (deUint16)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
722e5c31af7Sopenharmony_ci}
723e5c31af7Sopenharmony_ci
724e5c31af7Sopenharmony_citemplate<>
725e5c31af7Sopenharmony_ciinline GLValue::Byte getRandom (deRandom& rnd, GLValue::Byte min, GLValue::Byte max)
726e5c31af7Sopenharmony_ci{
727e5c31af7Sopenharmony_ci	if (max < min)
728e5c31af7Sopenharmony_ci		return min;
729e5c31af7Sopenharmony_ci
730e5c31af7Sopenharmony_ci	return GLValue::Byte::create((min == max ? min : (deInt8)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
731e5c31af7Sopenharmony_ci}
732e5c31af7Sopenharmony_ci
733e5c31af7Sopenharmony_citemplate<>
734e5c31af7Sopenharmony_ciinline GLValue::Ubyte getRandom (deRandom& rnd, GLValue::Ubyte min, GLValue::Ubyte max)
735e5c31af7Sopenharmony_ci{
736e5c31af7Sopenharmony_ci	if (max < min)
737e5c31af7Sopenharmony_ci		return min;
738e5c31af7Sopenharmony_ci
739e5c31af7Sopenharmony_ci	return GLValue::Ubyte::create((min == max ? min : (deUint8)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
740e5c31af7Sopenharmony_ci}
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_citemplate<>
743e5c31af7Sopenharmony_ciinline GLValue::Fixed getRandom (deRandom& rnd, GLValue::Fixed min, GLValue::Fixed max)
744e5c31af7Sopenharmony_ci{
745e5c31af7Sopenharmony_ci	if (max < min)
746e5c31af7Sopenharmony_ci		return min;
747e5c31af7Sopenharmony_ci
748e5c31af7Sopenharmony_ci	return GLValue::Fixed::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
749e5c31af7Sopenharmony_ci}
750e5c31af7Sopenharmony_ci
751e5c31af7Sopenharmony_citemplate<>
752e5c31af7Sopenharmony_ciinline GLValue::Half getRandom (deRandom& rnd, GLValue::Half min, GLValue::Half max)
753e5c31af7Sopenharmony_ci{
754e5c31af7Sopenharmony_ci	if (max < min)
755e5c31af7Sopenharmony_ci		return min;
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci	float fMax = max.to<float>();
758e5c31af7Sopenharmony_ci	float fMin = min.to<float>();
759e5c31af7Sopenharmony_ci	GLValue::Half h = GLValue::Half::create(fMin + deRandom_getFloat(&rnd) * (fMax - fMin));
760e5c31af7Sopenharmony_ci	return h;
761e5c31af7Sopenharmony_ci}
762e5c31af7Sopenharmony_ci
763e5c31af7Sopenharmony_citemplate<>
764e5c31af7Sopenharmony_ciinline GLValue::Int getRandom (deRandom& rnd, GLValue::Int min, GLValue::Int max)
765e5c31af7Sopenharmony_ci{
766e5c31af7Sopenharmony_ci	if (max < min)
767e5c31af7Sopenharmony_ci		return min;
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_ci	return GLValue::Int::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
770e5c31af7Sopenharmony_ci}
771e5c31af7Sopenharmony_ci
772e5c31af7Sopenharmony_citemplate<>
773e5c31af7Sopenharmony_ciinline GLValue::Uint getRandom (deRandom& rnd, GLValue::Uint min, GLValue::Uint max)
774e5c31af7Sopenharmony_ci{
775e5c31af7Sopenharmony_ci	if (max < min)
776e5c31af7Sopenharmony_ci		return min;
777e5c31af7Sopenharmony_ci
778e5c31af7Sopenharmony_ci	return GLValue::Uint::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
779e5c31af7Sopenharmony_ci}
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ci// Minimum difference required between coordinates
782e5c31af7Sopenharmony_citemplate<class T>
783e5c31af7Sopenharmony_ciinline T minValue (void);
784e5c31af7Sopenharmony_ci
785e5c31af7Sopenharmony_citemplate<>
786e5c31af7Sopenharmony_ciinline GLValue::Float minValue (void)
787e5c31af7Sopenharmony_ci{
788e5c31af7Sopenharmony_ci	return GLValue::Float::create(4 * 1.0f);
789e5c31af7Sopenharmony_ci}
790e5c31af7Sopenharmony_ci
791e5c31af7Sopenharmony_citemplate<>
792e5c31af7Sopenharmony_ciinline GLValue::Double minValue (void)
793e5c31af7Sopenharmony_ci{
794e5c31af7Sopenharmony_ci	return GLValue::Double::create(4 * 1.0f);
795e5c31af7Sopenharmony_ci}
796e5c31af7Sopenharmony_ci
797e5c31af7Sopenharmony_citemplate<>
798e5c31af7Sopenharmony_ciinline GLValue::Short minValue (void)
799e5c31af7Sopenharmony_ci{
800e5c31af7Sopenharmony_ci	return GLValue::Short::create(4 * 256);
801e5c31af7Sopenharmony_ci}
802e5c31af7Sopenharmony_ci
803e5c31af7Sopenharmony_citemplate<>
804e5c31af7Sopenharmony_ciinline GLValue::Ushort minValue (void)
805e5c31af7Sopenharmony_ci{
806e5c31af7Sopenharmony_ci	return GLValue::Ushort::create(4 * 256);
807e5c31af7Sopenharmony_ci}
808e5c31af7Sopenharmony_ci
809e5c31af7Sopenharmony_citemplate<>
810e5c31af7Sopenharmony_ciinline GLValue::Byte minValue (void)
811e5c31af7Sopenharmony_ci{
812e5c31af7Sopenharmony_ci	return GLValue::Byte::create(4 * 1);
813e5c31af7Sopenharmony_ci}
814e5c31af7Sopenharmony_ci
815e5c31af7Sopenharmony_citemplate<>
816e5c31af7Sopenharmony_ciinline GLValue::Ubyte minValue (void)
817e5c31af7Sopenharmony_ci{
818e5c31af7Sopenharmony_ci	return GLValue::Ubyte::create(4 * 2);
819e5c31af7Sopenharmony_ci}
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_citemplate<>
822e5c31af7Sopenharmony_ciinline GLValue::Fixed minValue (void)
823e5c31af7Sopenharmony_ci{
824e5c31af7Sopenharmony_ci	return GLValue::Fixed::create(4 * 1);
825e5c31af7Sopenharmony_ci}
826e5c31af7Sopenharmony_ci
827e5c31af7Sopenharmony_citemplate<>
828e5c31af7Sopenharmony_ciinline GLValue::Int minValue (void)
829e5c31af7Sopenharmony_ci{
830e5c31af7Sopenharmony_ci	return GLValue::Int::create(4 * 16777216);
831e5c31af7Sopenharmony_ci}
832e5c31af7Sopenharmony_ci
833e5c31af7Sopenharmony_citemplate<>
834e5c31af7Sopenharmony_ciinline GLValue::Uint minValue (void)
835e5c31af7Sopenharmony_ci{
836e5c31af7Sopenharmony_ci	return GLValue::Uint::create(4 * 16777216);
837e5c31af7Sopenharmony_ci}
838e5c31af7Sopenharmony_ci
839e5c31af7Sopenharmony_citemplate<>
840e5c31af7Sopenharmony_ciinline GLValue::Half minValue (void)
841e5c31af7Sopenharmony_ci{
842e5c31af7Sopenharmony_ci	return GLValue::Half::create(4 * 1.0f);
843e5c31af7Sopenharmony_ci}
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_citemplate<class T>
846e5c31af7Sopenharmony_ciinline T abs (T val);
847e5c31af7Sopenharmony_ci
848e5c31af7Sopenharmony_citemplate<>
849e5c31af7Sopenharmony_ciinline GLValue::Fixed abs (GLValue::Fixed val)
850e5c31af7Sopenharmony_ci{
851e5c31af7Sopenharmony_ci	return GLValue::Fixed::create(0x7FFFu & val.getValue());
852e5c31af7Sopenharmony_ci}
853e5c31af7Sopenharmony_ci
854e5c31af7Sopenharmony_citemplate<>
855e5c31af7Sopenharmony_ciinline GLValue::Ubyte abs (GLValue::Ubyte val)
856e5c31af7Sopenharmony_ci{
857e5c31af7Sopenharmony_ci	return val;
858e5c31af7Sopenharmony_ci}
859e5c31af7Sopenharmony_ci
860e5c31af7Sopenharmony_citemplate<>
861e5c31af7Sopenharmony_ciinline GLValue::Byte abs (GLValue::Byte val)
862e5c31af7Sopenharmony_ci{
863e5c31af7Sopenharmony_ci	return GLValue::Byte::create(0x7Fu & val.getValue());
864e5c31af7Sopenharmony_ci}
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_citemplate<>
867e5c31af7Sopenharmony_ciinline GLValue::Ushort abs (GLValue::Ushort val)
868e5c31af7Sopenharmony_ci{
869e5c31af7Sopenharmony_ci	return val;
870e5c31af7Sopenharmony_ci}
871e5c31af7Sopenharmony_ci
872e5c31af7Sopenharmony_citemplate<>
873e5c31af7Sopenharmony_ciinline GLValue::Short abs (GLValue::Short val)
874e5c31af7Sopenharmony_ci{
875e5c31af7Sopenharmony_ci	return GLValue::Short::create(0x7FFFu & val.getValue());
876e5c31af7Sopenharmony_ci}
877e5c31af7Sopenharmony_ci
878e5c31af7Sopenharmony_citemplate<>
879e5c31af7Sopenharmony_ciinline GLValue::Float abs (GLValue::Float val)
880e5c31af7Sopenharmony_ci{
881e5c31af7Sopenharmony_ci	return GLValue::Float::create(std::fabs(val.to<float>()));
882e5c31af7Sopenharmony_ci}
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_citemplate<>
885e5c31af7Sopenharmony_ciinline GLValue::Double abs (GLValue::Double val)
886e5c31af7Sopenharmony_ci{
887e5c31af7Sopenharmony_ci	return GLValue::Double::create(std::fabs(val.to<float>()));
888e5c31af7Sopenharmony_ci}
889e5c31af7Sopenharmony_ci
890e5c31af7Sopenharmony_citemplate<>
891e5c31af7Sopenharmony_ciinline GLValue::Uint abs (GLValue::Uint val)
892e5c31af7Sopenharmony_ci{
893e5c31af7Sopenharmony_ci	return val;
894e5c31af7Sopenharmony_ci}
895e5c31af7Sopenharmony_ci
896e5c31af7Sopenharmony_citemplate<>
897e5c31af7Sopenharmony_ciinline GLValue::Int abs (GLValue::Int val)
898e5c31af7Sopenharmony_ci{
899e5c31af7Sopenharmony_ci	return GLValue::Int::create(0x7FFFFFFFu & val.getValue());
900e5c31af7Sopenharmony_ci}
901e5c31af7Sopenharmony_ci
902e5c31af7Sopenharmony_citemplate<>
903e5c31af7Sopenharmony_ciinline GLValue::Half abs (GLValue::Half val)
904e5c31af7Sopenharmony_ci{
905e5c31af7Sopenharmony_ci	return GLValue::Half::create(std::fabs(val.to<float>()));
906e5c31af7Sopenharmony_ci}
907e5c31af7Sopenharmony_ci
908e5c31af7Sopenharmony_ci// AttributeArray
909e5c31af7Sopenharmony_ci
910e5c31af7Sopenharmony_ciclass AttributeArray
911e5c31af7Sopenharmony_ci{
912e5c31af7Sopenharmony_cipublic:
913e5c31af7Sopenharmony_ci								AttributeArray		(DrawTestSpec::Storage storage, sglr::Context& context);
914e5c31af7Sopenharmony_ci								~AttributeArray		(void);
915e5c31af7Sopenharmony_ci
916e5c31af7Sopenharmony_ci	void						data				(DrawTestSpec::Target target, size_t size, const char* data, DrawTestSpec::Usage usage);
917e5c31af7Sopenharmony_ci	void						setupArray			(bool bound, int offset, int size, DrawTestSpec::InputType inType, DrawTestSpec::OutputType outType, bool normalized, int stride, int instanceDivisor, const rr::GenericVec4& defaultAttrib, bool isPositionAttr, bool bgraComponentOrder);
918e5c31af7Sopenharmony_ci	void						bindAttribute		(deUint32 loc);
919e5c31af7Sopenharmony_ci	void						bindIndexArray		(DrawTestSpec::Target storage);
920e5c31af7Sopenharmony_ci
921e5c31af7Sopenharmony_ci	int							getComponentCount	(void) const { return m_componentCount; }
922e5c31af7Sopenharmony_ci	DrawTestSpec::Target		getTarget			(void) const { return m_target; }
923e5c31af7Sopenharmony_ci	DrawTestSpec::InputType		getInputType		(void) const { return m_inputType; }
924e5c31af7Sopenharmony_ci	DrawTestSpec::OutputType	getOutputType		(void) const { return m_outputType; }
925e5c31af7Sopenharmony_ci	DrawTestSpec::Storage		getStorageType		(void) const { return m_storage; }
926e5c31af7Sopenharmony_ci	bool						getNormalized		(void) const { return m_normalize; }
927e5c31af7Sopenharmony_ci	int							getStride			(void) const { return m_stride; }
928e5c31af7Sopenharmony_ci	bool						isBound				(void) const { return m_bound; }
929e5c31af7Sopenharmony_ci	bool						isPositionAttribute	(void) const { return m_isPositionAttr; }
930e5c31af7Sopenharmony_ci
931e5c31af7Sopenharmony_ciprivate:
932e5c31af7Sopenharmony_ci	DrawTestSpec::Storage		m_storage;
933e5c31af7Sopenharmony_ci	sglr::Context&				m_ctx;
934e5c31af7Sopenharmony_ci	deUint32					m_glBuffer;
935e5c31af7Sopenharmony_ci
936e5c31af7Sopenharmony_ci	int							m_size;
937e5c31af7Sopenharmony_ci	char*						m_data;
938e5c31af7Sopenharmony_ci	int							m_componentCount;
939e5c31af7Sopenharmony_ci	bool						m_bound;
940e5c31af7Sopenharmony_ci	DrawTestSpec::Target		m_target;
941e5c31af7Sopenharmony_ci	DrawTestSpec::InputType		m_inputType;
942e5c31af7Sopenharmony_ci	DrawTestSpec::OutputType	m_outputType;
943e5c31af7Sopenharmony_ci	bool						m_normalize;
944e5c31af7Sopenharmony_ci	int							m_stride;
945e5c31af7Sopenharmony_ci	int							m_offset;
946e5c31af7Sopenharmony_ci	rr::GenericVec4				m_defaultAttrib;
947e5c31af7Sopenharmony_ci	int							m_instanceDivisor;
948e5c31af7Sopenharmony_ci	bool						m_isPositionAttr;
949e5c31af7Sopenharmony_ci	bool						m_bgraOrder;
950e5c31af7Sopenharmony_ci};
951e5c31af7Sopenharmony_ci
952e5c31af7Sopenharmony_ciAttributeArray::AttributeArray (DrawTestSpec::Storage storage, sglr::Context& context)
953e5c31af7Sopenharmony_ci	: m_storage			(storage)
954e5c31af7Sopenharmony_ci	, m_ctx				(context)
955e5c31af7Sopenharmony_ci	, m_glBuffer		(0)
956e5c31af7Sopenharmony_ci	, m_size			(0)
957e5c31af7Sopenharmony_ci	, m_data			(DE_NULL)
958e5c31af7Sopenharmony_ci	, m_componentCount	(1)
959e5c31af7Sopenharmony_ci	, m_bound			(false)
960e5c31af7Sopenharmony_ci	, m_target			(DrawTestSpec::TARGET_ARRAY)
961e5c31af7Sopenharmony_ci	, m_inputType		(DrawTestSpec::INPUTTYPE_FLOAT)
962e5c31af7Sopenharmony_ci	, m_outputType		(DrawTestSpec::OUTPUTTYPE_VEC4)
963e5c31af7Sopenharmony_ci	, m_normalize		(false)
964e5c31af7Sopenharmony_ci	, m_stride			(0)
965e5c31af7Sopenharmony_ci	, m_offset			(0)
966e5c31af7Sopenharmony_ci	, m_instanceDivisor	(0)
967e5c31af7Sopenharmony_ci	, m_isPositionAttr	(false)
968e5c31af7Sopenharmony_ci	, m_bgraOrder		(false)
969e5c31af7Sopenharmony_ci{
970e5c31af7Sopenharmony_ci	if (m_storage == DrawTestSpec::STORAGE_BUFFER)
971e5c31af7Sopenharmony_ci	{
972e5c31af7Sopenharmony_ci		m_ctx.genBuffers(1, &m_glBuffer);
973e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glGenBuffers()");
974e5c31af7Sopenharmony_ci	}
975e5c31af7Sopenharmony_ci}
976e5c31af7Sopenharmony_ci
977e5c31af7Sopenharmony_ciAttributeArray::~AttributeArray	(void)
978e5c31af7Sopenharmony_ci{
979e5c31af7Sopenharmony_ci	if (m_storage == DrawTestSpec::STORAGE_BUFFER)
980e5c31af7Sopenharmony_ci	{
981e5c31af7Sopenharmony_ci		m_ctx.deleteBuffers(1, &m_glBuffer);
982e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDeleteBuffers()");
983e5c31af7Sopenharmony_ci	}
984e5c31af7Sopenharmony_ci	else if (m_storage == DrawTestSpec::STORAGE_USER)
985e5c31af7Sopenharmony_ci		delete[] m_data;
986e5c31af7Sopenharmony_ci	else
987e5c31af7Sopenharmony_ci		DE_ASSERT(false);
988e5c31af7Sopenharmony_ci}
989e5c31af7Sopenharmony_ci
990e5c31af7Sopenharmony_civoid AttributeArray::data (DrawTestSpec::Target target, size_t size, const char* ptr, DrawTestSpec::Usage usage)
991e5c31af7Sopenharmony_ci{
992e5c31af7Sopenharmony_ci	m_size = (int)size;
993e5c31af7Sopenharmony_ci	m_target = target;
994e5c31af7Sopenharmony_ci
995e5c31af7Sopenharmony_ci	if (m_storage == DrawTestSpec::STORAGE_BUFFER)
996e5c31af7Sopenharmony_ci	{
997e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
998e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
999e5c31af7Sopenharmony_ci
1000e5c31af7Sopenharmony_ci		m_ctx.bufferData(targetToGL(target), size, ptr, usageToGL(usage));
1001e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferData()");
1002e5c31af7Sopenharmony_ci	}
1003e5c31af7Sopenharmony_ci	else if (m_storage == DrawTestSpec::STORAGE_USER)
1004e5c31af7Sopenharmony_ci	{
1005e5c31af7Sopenharmony_ci		if (m_data)
1006e5c31af7Sopenharmony_ci			delete[] m_data;
1007e5c31af7Sopenharmony_ci
1008e5c31af7Sopenharmony_ci		m_data = new char[size];
1009e5c31af7Sopenharmony_ci		std::memcpy(m_data, ptr, size);
1010e5c31af7Sopenharmony_ci	}
1011e5c31af7Sopenharmony_ci	else
1012e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1013e5c31af7Sopenharmony_ci}
1014e5c31af7Sopenharmony_ci
1015e5c31af7Sopenharmony_civoid AttributeArray::setupArray (bool bound, int offset, int size, DrawTestSpec::InputType inputType, DrawTestSpec::OutputType outType, bool normalized, int stride, int instanceDivisor, const rr::GenericVec4& defaultAttrib, bool isPositionAttr, bool bgraComponentOrder)
1016e5c31af7Sopenharmony_ci{
1017e5c31af7Sopenharmony_ci	m_componentCount	= size;
1018e5c31af7Sopenharmony_ci	m_bound				= bound;
1019e5c31af7Sopenharmony_ci	m_inputType			= inputType;
1020e5c31af7Sopenharmony_ci	m_outputType		= outType;
1021e5c31af7Sopenharmony_ci	m_normalize			= normalized;
1022e5c31af7Sopenharmony_ci	m_stride			= stride;
1023e5c31af7Sopenharmony_ci	m_offset			= offset;
1024e5c31af7Sopenharmony_ci	m_defaultAttrib		= defaultAttrib;
1025e5c31af7Sopenharmony_ci	m_instanceDivisor	= instanceDivisor;
1026e5c31af7Sopenharmony_ci	m_isPositionAttr	= isPositionAttr;
1027e5c31af7Sopenharmony_ci	m_bgraOrder			= bgraComponentOrder;
1028e5c31af7Sopenharmony_ci}
1029e5c31af7Sopenharmony_ci
1030e5c31af7Sopenharmony_civoid AttributeArray::bindAttribute (deUint32 loc)
1031e5c31af7Sopenharmony_ci{
1032e5c31af7Sopenharmony_ci	if (!isBound())
1033e5c31af7Sopenharmony_ci	{
1034e5c31af7Sopenharmony_ci		switch (m_inputType)
1035e5c31af7Sopenharmony_ci		{
1036e5c31af7Sopenharmony_ci			case DrawTestSpec::INPUTTYPE_FLOAT:
1037e5c31af7Sopenharmony_ci			{
1038e5c31af7Sopenharmony_ci				tcu::Vec4 attr = m_defaultAttrib.get<float>();
1039e5c31af7Sopenharmony_ci
1040e5c31af7Sopenharmony_ci				switch (m_componentCount)
1041e5c31af7Sopenharmony_ci				{
1042e5c31af7Sopenharmony_ci					case 1: m_ctx.vertexAttrib1f(loc, attr.x()); break;
1043e5c31af7Sopenharmony_ci					case 2: m_ctx.vertexAttrib2f(loc, attr.x(), attr.y()); break;
1044e5c31af7Sopenharmony_ci					case 3: m_ctx.vertexAttrib3f(loc, attr.x(), attr.y(), attr.z()); break;
1045e5c31af7Sopenharmony_ci					case 4: m_ctx.vertexAttrib4f(loc, attr.x(), attr.y(), attr.z(), attr.w()); break;
1046e5c31af7Sopenharmony_ci					default: DE_ASSERT(DE_FALSE); break;
1047e5c31af7Sopenharmony_ci				}
1048e5c31af7Sopenharmony_ci				break;
1049e5c31af7Sopenharmony_ci			}
1050e5c31af7Sopenharmony_ci			case DrawTestSpec::INPUTTYPE_INT:
1051e5c31af7Sopenharmony_ci			{
1052e5c31af7Sopenharmony_ci				tcu::IVec4 attr = m_defaultAttrib.get<deInt32>();
1053e5c31af7Sopenharmony_ci				m_ctx.vertexAttribI4i(loc, attr.x(), attr.y(), attr.z(), attr.w());
1054e5c31af7Sopenharmony_ci				break;
1055e5c31af7Sopenharmony_ci			}
1056e5c31af7Sopenharmony_ci			case DrawTestSpec::INPUTTYPE_UNSIGNED_INT:
1057e5c31af7Sopenharmony_ci			{
1058e5c31af7Sopenharmony_ci				tcu::UVec4 attr = m_defaultAttrib.get<deUint32>();
1059e5c31af7Sopenharmony_ci				m_ctx.vertexAttribI4ui(loc, attr.x(), attr.y(), attr.z(), attr.w());
1060e5c31af7Sopenharmony_ci				break;
1061e5c31af7Sopenharmony_ci			}
1062e5c31af7Sopenharmony_ci			default:
1063e5c31af7Sopenharmony_ci				DE_ASSERT(DE_FALSE);
1064e5c31af7Sopenharmony_ci				break;
1065e5c31af7Sopenharmony_ci		}
1066e5c31af7Sopenharmony_ci	}
1067e5c31af7Sopenharmony_ci	else
1068e5c31af7Sopenharmony_ci	{
1069e5c31af7Sopenharmony_ci		const deUint8* basePtr = DE_NULL;
1070e5c31af7Sopenharmony_ci
1071e5c31af7Sopenharmony_ci		if (m_storage == DrawTestSpec::STORAGE_BUFFER)
1072e5c31af7Sopenharmony_ci		{
1073e5c31af7Sopenharmony_ci			m_ctx.bindBuffer(targetToGL(m_target), m_glBuffer);
1074e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
1075e5c31af7Sopenharmony_ci
1076e5c31af7Sopenharmony_ci			basePtr = DE_NULL;
1077e5c31af7Sopenharmony_ci		}
1078e5c31af7Sopenharmony_ci		else if (m_storage == DrawTestSpec::STORAGE_USER)
1079e5c31af7Sopenharmony_ci		{
1080e5c31af7Sopenharmony_ci			m_ctx.bindBuffer(targetToGL(m_target), 0);
1081e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
1082e5c31af7Sopenharmony_ci
1083e5c31af7Sopenharmony_ci			basePtr = (const deUint8*)m_data;
1084e5c31af7Sopenharmony_ci		}
1085e5c31af7Sopenharmony_ci		else
1086e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
1087e5c31af7Sopenharmony_ci
1088e5c31af7Sopenharmony_ci		if (!inputTypeIsFloatType(m_inputType))
1089e5c31af7Sopenharmony_ci		{
1090e5c31af7Sopenharmony_ci			// Input is not float type
1091e5c31af7Sopenharmony_ci
1092e5c31af7Sopenharmony_ci			if (outputTypeIsFloatType(m_outputType))
1093e5c31af7Sopenharmony_ci			{
1094e5c31af7Sopenharmony_ci				const int size = (m_bgraOrder) ? (GL_BGRA) : (m_componentCount);
1095e5c31af7Sopenharmony_ci
1096e5c31af7Sopenharmony_ci				DE_ASSERT(!(m_bgraOrder && m_componentCount != 4));
1097e5c31af7Sopenharmony_ci
1098e5c31af7Sopenharmony_ci				// Output type is float type
1099e5c31af7Sopenharmony_ci				m_ctx.vertexAttribPointer(loc, size, inputTypeToGL(m_inputType), m_normalize, m_stride, basePtr + m_offset);
1100e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
1101e5c31af7Sopenharmony_ci			}
1102e5c31af7Sopenharmony_ci			else
1103e5c31af7Sopenharmony_ci			{
1104e5c31af7Sopenharmony_ci				// Output type is int type
1105e5c31af7Sopenharmony_ci				m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, basePtr + m_offset);
1106e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()");
1107e5c31af7Sopenharmony_ci			}
1108e5c31af7Sopenharmony_ci		}
1109e5c31af7Sopenharmony_ci		else
1110e5c31af7Sopenharmony_ci		{
1111e5c31af7Sopenharmony_ci			// Input type is float type
1112e5c31af7Sopenharmony_ci
1113e5c31af7Sopenharmony_ci			// Output type must be float type
1114e5c31af7Sopenharmony_ci			DE_ASSERT(outputTypeIsFloatType(m_outputType));
1115e5c31af7Sopenharmony_ci
1116e5c31af7Sopenharmony_ci			m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, basePtr + m_offset);
1117e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
1118e5c31af7Sopenharmony_ci		}
1119e5c31af7Sopenharmony_ci
1120e5c31af7Sopenharmony_ci		if (m_instanceDivisor)
1121e5c31af7Sopenharmony_ci			m_ctx.vertexAttribDivisor(loc, m_instanceDivisor);
1122e5c31af7Sopenharmony_ci	}
1123e5c31af7Sopenharmony_ci}
1124e5c31af7Sopenharmony_ci
1125e5c31af7Sopenharmony_civoid AttributeArray::bindIndexArray (DrawTestSpec::Target target)
1126e5c31af7Sopenharmony_ci{
1127e5c31af7Sopenharmony_ci	if (m_storage == DrawTestSpec::STORAGE_USER)
1128e5c31af7Sopenharmony_ci	{
1129e5c31af7Sopenharmony_ci	}
1130e5c31af7Sopenharmony_ci	else if (m_storage == DrawTestSpec::STORAGE_BUFFER)
1131e5c31af7Sopenharmony_ci	{
1132e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
1133e5c31af7Sopenharmony_ci	}
1134e5c31af7Sopenharmony_ci}
1135e5c31af7Sopenharmony_ci
1136e5c31af7Sopenharmony_ci// DrawTestShaderProgram
1137e5c31af7Sopenharmony_ci
1138e5c31af7Sopenharmony_ciclass DrawTestShaderProgram : public sglr::ShaderProgram
1139e5c31af7Sopenharmony_ci{
1140e5c31af7Sopenharmony_cipublic:
1141e5c31af7Sopenharmony_ci												DrawTestShaderProgram		(const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays);
1142e5c31af7Sopenharmony_ci
1143e5c31af7Sopenharmony_ci	void										shadeVertices				(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
1144e5c31af7Sopenharmony_ci	void										shadeFragments				(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
1145e5c31af7Sopenharmony_ci
1146e5c31af7Sopenharmony_ciprivate:
1147e5c31af7Sopenharmony_ci	static std::string							genVertexSource				(const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays);
1148e5c31af7Sopenharmony_ci	static std::string							genFragmentSource			(const glu::RenderContext& ctx);
1149e5c31af7Sopenharmony_ci	static void									generateShaderParams		(std::map<std::string, std::string>& params, glu::ContextType type);
1150e5c31af7Sopenharmony_ci	static rr::GenericVecType					mapOutputType				(const DrawTestSpec::OutputType& type);
1151e5c31af7Sopenharmony_ci	static int									getComponentCount			(const DrawTestSpec::OutputType& type);
1152e5c31af7Sopenharmony_ci
1153e5c31af7Sopenharmony_ci	static sglr::pdec::ShaderProgramDeclaration createProgramDeclaration	(const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays);
1154e5c31af7Sopenharmony_ci
1155e5c31af7Sopenharmony_ci	std::vector<int>							m_componentCount;
1156e5c31af7Sopenharmony_ci	std::vector<bool>							m_isCoord;
1157e5c31af7Sopenharmony_ci	std::vector<rr::GenericVecType>				m_attrType;
1158e5c31af7Sopenharmony_ci};
1159e5c31af7Sopenharmony_ci
1160e5c31af7Sopenharmony_ciDrawTestShaderProgram::DrawTestShaderProgram (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays)
1161e5c31af7Sopenharmony_ci	: sglr::ShaderProgram	(createProgramDeclaration(ctx, arrays))
1162e5c31af7Sopenharmony_ci	, m_componentCount		(arrays.size())
1163e5c31af7Sopenharmony_ci	, m_isCoord				(arrays.size())
1164e5c31af7Sopenharmony_ci	, m_attrType			(arrays.size())
1165e5c31af7Sopenharmony_ci{
1166e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1167e5c31af7Sopenharmony_ci	{
1168e5c31af7Sopenharmony_ci		m_componentCount[arrayNdx]	= getComponentCount(arrays[arrayNdx]->getOutputType());
1169e5c31af7Sopenharmony_ci		m_isCoord[arrayNdx]			= arrays[arrayNdx]->isPositionAttribute();
1170e5c31af7Sopenharmony_ci		m_attrType[arrayNdx]		= mapOutputType(arrays[arrayNdx]->getOutputType());
1171e5c31af7Sopenharmony_ci	}
1172e5c31af7Sopenharmony_ci}
1173e5c31af7Sopenharmony_ci
1174e5c31af7Sopenharmony_citemplate <typename T>
1175e5c31af7Sopenharmony_civoid calcShaderColorCoord (tcu::Vec2& coord, tcu::Vec3& color, const tcu::Vector<T, 4>& attribValue, bool isCoordinate, int numComponents)
1176e5c31af7Sopenharmony_ci{
1177e5c31af7Sopenharmony_ci	if (isCoordinate)
1178e5c31af7Sopenharmony_ci		switch (numComponents)
1179e5c31af7Sopenharmony_ci		{
1180e5c31af7Sopenharmony_ci			case 1:	coord += tcu::Vec2((float)attribValue.x(),							(float)attribValue.x());							break;
1181e5c31af7Sopenharmony_ci			case 2:	coord += tcu::Vec2((float)attribValue.x(),							(float)attribValue.y());							break;
1182e5c31af7Sopenharmony_ci			case 3:	coord += tcu::Vec2((float)attribValue.x() + (float)attribValue.z(),	(float)attribValue.y());							break;
1183e5c31af7Sopenharmony_ci			case 4:	coord += tcu::Vec2((float)attribValue.x() + (float)attribValue.z(),	(float)attribValue.y() + (float)attribValue.w());	break;
1184e5c31af7Sopenharmony_ci
1185e5c31af7Sopenharmony_ci			default:
1186e5c31af7Sopenharmony_ci				DE_ASSERT(false);
1187e5c31af7Sopenharmony_ci		}
1188e5c31af7Sopenharmony_ci	else
1189e5c31af7Sopenharmony_ci	{
1190e5c31af7Sopenharmony_ci		switch (numComponents)
1191e5c31af7Sopenharmony_ci		{
1192e5c31af7Sopenharmony_ci			case 1:
1193e5c31af7Sopenharmony_ci				color = color * (float)attribValue.x();
1194e5c31af7Sopenharmony_ci				break;
1195e5c31af7Sopenharmony_ci
1196e5c31af7Sopenharmony_ci			case 2:
1197e5c31af7Sopenharmony_ci				color.x() = color.x() * (float)attribValue.x();
1198e5c31af7Sopenharmony_ci				color.y() = color.y() * (float)attribValue.y();
1199e5c31af7Sopenharmony_ci				break;
1200e5c31af7Sopenharmony_ci
1201e5c31af7Sopenharmony_ci			case 3:
1202e5c31af7Sopenharmony_ci				color.x() = color.x() * (float)attribValue.x();
1203e5c31af7Sopenharmony_ci				color.y() = color.y() * (float)attribValue.y();
1204e5c31af7Sopenharmony_ci				color.z() = color.z() * (float)attribValue.z();
1205e5c31af7Sopenharmony_ci				break;
1206e5c31af7Sopenharmony_ci
1207e5c31af7Sopenharmony_ci			case 4:
1208e5c31af7Sopenharmony_ci				color.x() = color.x() * (float)attribValue.x() * (float)attribValue.w();
1209e5c31af7Sopenharmony_ci				color.y() = color.y() * (float)attribValue.y() * (float)attribValue.w();
1210e5c31af7Sopenharmony_ci				color.z() = color.z() * (float)attribValue.z() * (float)attribValue.w();
1211e5c31af7Sopenharmony_ci				break;
1212e5c31af7Sopenharmony_ci
1213e5c31af7Sopenharmony_ci			default:
1214e5c31af7Sopenharmony_ci				DE_ASSERT(false);
1215e5c31af7Sopenharmony_ci		}
1216e5c31af7Sopenharmony_ci	}
1217e5c31af7Sopenharmony_ci}
1218e5c31af7Sopenharmony_ci
1219e5c31af7Sopenharmony_civoid DrawTestShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
1220e5c31af7Sopenharmony_ci{
1221e5c31af7Sopenharmony_ci	const float	u_coordScale = getUniformByName("u_coordScale").value.f;
1222e5c31af7Sopenharmony_ci	const float u_colorScale = getUniformByName("u_colorScale").value.f;
1223e5c31af7Sopenharmony_ci
1224e5c31af7Sopenharmony_ci	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1225e5c31af7Sopenharmony_ci	{
1226e5c31af7Sopenharmony_ci		const size_t varyingLocColor = 0;
1227e5c31af7Sopenharmony_ci
1228e5c31af7Sopenharmony_ci		rr::VertexPacket& packet = *packets[packetNdx];
1229e5c31af7Sopenharmony_ci
1230e5c31af7Sopenharmony_ci		// Calc output color
1231e5c31af7Sopenharmony_ci		tcu::Vec2 coord = tcu::Vec2(0.0, 0.0);
1232e5c31af7Sopenharmony_ci		tcu::Vec3 color = tcu::Vec3(1.0, 1.0, 1.0);
1233e5c31af7Sopenharmony_ci
1234e5c31af7Sopenharmony_ci		for (int attribNdx = 0; attribNdx < (int)m_attrType.size(); attribNdx++)
1235e5c31af7Sopenharmony_ci		{
1236e5c31af7Sopenharmony_ci			const int	numComponents	= m_componentCount[attribNdx];
1237e5c31af7Sopenharmony_ci			const bool	isCoord			= m_isCoord[attribNdx];
1238e5c31af7Sopenharmony_ci
1239e5c31af7Sopenharmony_ci			switch (m_attrType[attribNdx])
1240e5c31af7Sopenharmony_ci			{
1241e5c31af7Sopenharmony_ci				case rr::GENERICVECTYPE_FLOAT:	calcShaderColorCoord(coord, color, rr::readVertexAttribFloat(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), isCoord, numComponents);	break;
1242e5c31af7Sopenharmony_ci				case rr::GENERICVECTYPE_INT32:	calcShaderColorCoord(coord, color, rr::readVertexAttribInt	(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), isCoord, numComponents);	break;
1243e5c31af7Sopenharmony_ci				case rr::GENERICVECTYPE_UINT32:	calcShaderColorCoord(coord, color, rr::readVertexAttribUint	(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), isCoord, numComponents);	break;
1244e5c31af7Sopenharmony_ci				default:
1245e5c31af7Sopenharmony_ci					DE_ASSERT(false);
1246e5c31af7Sopenharmony_ci			}
1247e5c31af7Sopenharmony_ci		}
1248e5c31af7Sopenharmony_ci
1249e5c31af7Sopenharmony_ci		// Transform position
1250e5c31af7Sopenharmony_ci		{
1251e5c31af7Sopenharmony_ci			packet.position = tcu::Vec4(u_coordScale * coord.x(), u_coordScale * coord.y(), 1.0f, 1.0f);
1252e5c31af7Sopenharmony_ci			packet.pointSize = 1.0f;
1253e5c31af7Sopenharmony_ci		}
1254e5c31af7Sopenharmony_ci
1255e5c31af7Sopenharmony_ci		// Pass color to FS
1256e5c31af7Sopenharmony_ci		{
1257e5c31af7Sopenharmony_ci			packet.outputs[varyingLocColor] = tcu::Vec4(u_colorScale * color.x(), u_colorScale * color.y(), u_colorScale * color.z(), 1.0f) * 0.5f + tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
1258e5c31af7Sopenharmony_ci		}
1259e5c31af7Sopenharmony_ci	}
1260e5c31af7Sopenharmony_ci}
1261e5c31af7Sopenharmony_ci
1262e5c31af7Sopenharmony_civoid DrawTestShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
1263e5c31af7Sopenharmony_ci{
1264e5c31af7Sopenharmony_ci	const size_t varyingLocColor = 0;
1265e5c31af7Sopenharmony_ci
1266e5c31af7Sopenharmony_ci	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
1267e5c31af7Sopenharmony_ci	{
1268e5c31af7Sopenharmony_ci		rr::FragmentPacket& packet = packets[packetNdx];
1269e5c31af7Sopenharmony_ci
1270e5c31af7Sopenharmony_ci		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
1271e5c31af7Sopenharmony_ci			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, varyingLocColor, fragNdx));
1272e5c31af7Sopenharmony_ci	}
1273e5c31af7Sopenharmony_ci}
1274e5c31af7Sopenharmony_ci
1275e5c31af7Sopenharmony_cistd::string DrawTestShaderProgram::genVertexSource (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays)
1276e5c31af7Sopenharmony_ci{
1277e5c31af7Sopenharmony_ci	std::map<std::string, std::string>	params;
1278e5c31af7Sopenharmony_ci	std::stringstream					vertexShaderTmpl;
1279e5c31af7Sopenharmony_ci
1280e5c31af7Sopenharmony_ci	generateShaderParams(params, ctx.getType());
1281e5c31af7Sopenharmony_ci
1282e5c31af7Sopenharmony_ci	vertexShaderTmpl << "${VTX_HDR}";
1283e5c31af7Sopenharmony_ci
1284e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1285e5c31af7Sopenharmony_ci	{
1286e5c31af7Sopenharmony_ci		vertexShaderTmpl
1287e5c31af7Sopenharmony_ci			<< "${VTX_IN} highp " << outputTypeToGLType(arrays[arrayNdx]->getOutputType()) << " a_" << arrayNdx << ";\n";
1288e5c31af7Sopenharmony_ci	}
1289e5c31af7Sopenharmony_ci
1290e5c31af7Sopenharmony_ci	vertexShaderTmpl <<
1291e5c31af7Sopenharmony_ci		"uniform highp float u_coordScale;\n"
1292e5c31af7Sopenharmony_ci		"uniform highp float u_colorScale;\n"
1293e5c31af7Sopenharmony_ci		"${VTX_OUT} ${COL_PRECISION} vec4 v_color;\n"
1294e5c31af7Sopenharmony_ci		"void main(void)\n"
1295e5c31af7Sopenharmony_ci		"{\n"
1296e5c31af7Sopenharmony_ci		"\tgl_PointSize = 1.0;\n"
1297e5c31af7Sopenharmony_ci		"\thighp vec2 coord = vec2(0.0, 0.0);\n"
1298e5c31af7Sopenharmony_ci		"\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n";
1299e5c31af7Sopenharmony_ci
1300e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1301e5c31af7Sopenharmony_ci	{
1302e5c31af7Sopenharmony_ci		const bool isPositionAttr = arrays[arrayNdx]->isPositionAttribute();
1303e5c31af7Sopenharmony_ci
1304e5c31af7Sopenharmony_ci		if (isPositionAttr)
1305e5c31af7Sopenharmony_ci		{
1306e5c31af7Sopenharmony_ci			switch (arrays[arrayNdx]->getOutputType())
1307e5c31af7Sopenharmony_ci			{
1308e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1309e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_INT):
1310e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UINT):
1311e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1312e5c31af7Sopenharmony_ci						"\tcoord += vec2(float(a_" << arrayNdx << "), float(a_" << arrayNdx << "));\n";
1313e5c31af7Sopenharmony_ci					break;
1314e5c31af7Sopenharmony_ci
1315e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_VEC2):
1316e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1317e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1318e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1319e5c31af7Sopenharmony_ci						"\tcoord += vec2(a_" << arrayNdx << ".xy);\n";
1320e5c31af7Sopenharmony_ci					break;
1321e5c31af7Sopenharmony_ci
1322e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_VEC3):
1323e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1324e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1325e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1326e5c31af7Sopenharmony_ci						"\tcoord += vec2(a_" << arrayNdx << ".xy);\n"
1327e5c31af7Sopenharmony_ci						"\tcoord.x += float(a_" << arrayNdx << ".z);\n";
1328e5c31af7Sopenharmony_ci					break;
1329e5c31af7Sopenharmony_ci
1330e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_VEC4):
1331e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1332e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1333e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1334e5c31af7Sopenharmony_ci						"\tcoord += vec2(a_" << arrayNdx << ".xy);\n"
1335e5c31af7Sopenharmony_ci						"\tcoord += vec2(a_" << arrayNdx << ".zw);\n";
1336e5c31af7Sopenharmony_ci					break;
1337e5c31af7Sopenharmony_ci
1338e5c31af7Sopenharmony_ci				default:
1339e5c31af7Sopenharmony_ci					DE_ASSERT(false);
1340e5c31af7Sopenharmony_ci					break;
1341e5c31af7Sopenharmony_ci			}
1342e5c31af7Sopenharmony_ci		}
1343e5c31af7Sopenharmony_ci		else
1344e5c31af7Sopenharmony_ci		{
1345e5c31af7Sopenharmony_ci			switch (arrays[arrayNdx]->getOutputType())
1346e5c31af7Sopenharmony_ci			{
1347e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1348e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_INT):
1349e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UINT):
1350e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1351e5c31af7Sopenharmony_ci						"\tcolor = color * float(a_" << arrayNdx << ");\n";
1352e5c31af7Sopenharmony_ci					break;
1353e5c31af7Sopenharmony_ci
1354e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_VEC2):
1355e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1356e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1357e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1358e5c31af7Sopenharmony_ci						"\tcolor.rg = color.rg * vec2(a_" << arrayNdx << ".xy);\n";
1359e5c31af7Sopenharmony_ci					break;
1360e5c31af7Sopenharmony_ci
1361e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_VEC3):
1362e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1363e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1364e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1365e5c31af7Sopenharmony_ci						"\tcolor = color.rgb * vec3(a_" << arrayNdx << ".xyz);\n";
1366e5c31af7Sopenharmony_ci					break;
1367e5c31af7Sopenharmony_ci
1368e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_VEC4):
1369e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1370e5c31af7Sopenharmony_ci				case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1371e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
1372e5c31af7Sopenharmony_ci						"\tcolor = color.rgb * vec3(a_" << arrayNdx << ".xyz) * float(a_" << arrayNdx << ".w);\n";
1373e5c31af7Sopenharmony_ci					break;
1374e5c31af7Sopenharmony_ci
1375e5c31af7Sopenharmony_ci				default:
1376e5c31af7Sopenharmony_ci					DE_ASSERT(false);
1377e5c31af7Sopenharmony_ci					break;
1378e5c31af7Sopenharmony_ci			}
1379e5c31af7Sopenharmony_ci		}
1380e5c31af7Sopenharmony_ci	}
1381e5c31af7Sopenharmony_ci
1382e5c31af7Sopenharmony_ci	vertexShaderTmpl <<
1383e5c31af7Sopenharmony_ci		"\tv_color = vec4(u_colorScale * color, 1.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5);\n"
1384e5c31af7Sopenharmony_ci		"\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n"
1385e5c31af7Sopenharmony_ci		"}\n";
1386e5c31af7Sopenharmony_ci
1387e5c31af7Sopenharmony_ci	return tcu::StringTemplate(vertexShaderTmpl.str().c_str()).specialize(params);
1388e5c31af7Sopenharmony_ci}
1389e5c31af7Sopenharmony_ci
1390e5c31af7Sopenharmony_cistd::string DrawTestShaderProgram::genFragmentSource (const glu::RenderContext& ctx)
1391e5c31af7Sopenharmony_ci{
1392e5c31af7Sopenharmony_ci	std::map<std::string, std::string> params;
1393e5c31af7Sopenharmony_ci
1394e5c31af7Sopenharmony_ci	generateShaderParams(params, ctx.getType());
1395e5c31af7Sopenharmony_ci
1396e5c31af7Sopenharmony_ci	static const char* fragmentShaderTmpl =
1397e5c31af7Sopenharmony_ci		"${FRAG_HDR}"
1398e5c31af7Sopenharmony_ci		"${FRAG_IN} ${COL_PRECISION} vec4 v_color;\n"
1399e5c31af7Sopenharmony_ci		"void main(void)\n"
1400e5c31af7Sopenharmony_ci		"{\n"
1401e5c31af7Sopenharmony_ci		"\t${FRAG_COLOR} = v_color;\n"
1402e5c31af7Sopenharmony_ci		"}\n";
1403e5c31af7Sopenharmony_ci
1404e5c31af7Sopenharmony_ci	return tcu::StringTemplate(fragmentShaderTmpl).specialize(params);
1405e5c31af7Sopenharmony_ci}
1406e5c31af7Sopenharmony_ci
1407e5c31af7Sopenharmony_civoid DrawTestShaderProgram::generateShaderParams (std::map<std::string, std::string>& params, glu::ContextType type)
1408e5c31af7Sopenharmony_ci{
1409e5c31af7Sopenharmony_ci	if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_300_ES))
1410e5c31af7Sopenharmony_ci	{
1411e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "in";
1412e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "out";
1413e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "in";
1414e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "dEQP_FragColor";
1415e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "#version 300 es\n";
1416e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1417e5c31af7Sopenharmony_ci		params["COL_PRECISION"]	= "mediump";
1418e5c31af7Sopenharmony_ci	}
1419e5c31af7Sopenharmony_ci	else if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_100_ES))
1420e5c31af7Sopenharmony_ci	{
1421e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "attribute";
1422e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "varying";
1423e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "varying";
1424e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "gl_FragColor";
1425e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "";
1426e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "";
1427e5c31af7Sopenharmony_ci		params["COL_PRECISION"]	= "mediump";
1428e5c31af7Sopenharmony_ci	}
1429e5c31af7Sopenharmony_ci	else if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_430))
1430e5c31af7Sopenharmony_ci	{
1431e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "in";
1432e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "out";
1433e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "in";
1434e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "dEQP_FragColor";
1435e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "#version 430\n";
1436e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "#version 430\nlayout(location = 0) out highp vec4 dEQP_FragColor;\n";
1437e5c31af7Sopenharmony_ci		params["COL_PRECISION"]	= "highp";
1438e5c31af7Sopenharmony_ci	}
1439e5c31af7Sopenharmony_ci	else if (glu::isGLSLVersionSupported(type, glu::GLSL_VERSION_330))
1440e5c31af7Sopenharmony_ci	{
1441e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "in";
1442e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "out";
1443e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "in";
1444e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "dEQP_FragColor";
1445e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "#version 330\n";
1446e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
1447e5c31af7Sopenharmony_ci		params["COL_PRECISION"]	= "mediump";
1448e5c31af7Sopenharmony_ci	}
1449e5c31af7Sopenharmony_ci	else
1450e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
1451e5c31af7Sopenharmony_ci}
1452e5c31af7Sopenharmony_ci
1453e5c31af7Sopenharmony_cirr::GenericVecType DrawTestShaderProgram::mapOutputType (const DrawTestSpec::OutputType& type)
1454e5c31af7Sopenharmony_ci{
1455e5c31af7Sopenharmony_ci	switch (type)
1456e5c31af7Sopenharmony_ci	{
1457e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1458e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_VEC2):
1459e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_VEC3):
1460e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_VEC4):
1461e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_FLOAT;
1462e5c31af7Sopenharmony_ci
1463e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_INT):
1464e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1465e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1466e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1467e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_INT32;
1468e5c31af7Sopenharmony_ci
1469e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UINT):
1470e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1471e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1472e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1473e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_UINT32;
1474e5c31af7Sopenharmony_ci
1475e5c31af7Sopenharmony_ci		default:
1476e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1477e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_LAST;
1478e5c31af7Sopenharmony_ci	}
1479e5c31af7Sopenharmony_ci}
1480e5c31af7Sopenharmony_ci
1481e5c31af7Sopenharmony_ciint DrawTestShaderProgram::getComponentCount (const DrawTestSpec::OutputType& type)
1482e5c31af7Sopenharmony_ci{
1483e5c31af7Sopenharmony_ci	switch (type)
1484e5c31af7Sopenharmony_ci	{
1485e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_FLOAT):
1486e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_INT):
1487e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UINT):
1488e5c31af7Sopenharmony_ci			return 1;
1489e5c31af7Sopenharmony_ci
1490e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_VEC2):
1491e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_IVEC2):
1492e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UVEC2):
1493e5c31af7Sopenharmony_ci			return 2;
1494e5c31af7Sopenharmony_ci
1495e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_VEC3):
1496e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_IVEC3):
1497e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UVEC3):
1498e5c31af7Sopenharmony_ci			return 3;
1499e5c31af7Sopenharmony_ci
1500e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_VEC4):
1501e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_IVEC4):
1502e5c31af7Sopenharmony_ci		case (DrawTestSpec::OUTPUTTYPE_UVEC4):
1503e5c31af7Sopenharmony_ci			return 4;
1504e5c31af7Sopenharmony_ci
1505e5c31af7Sopenharmony_ci		default:
1506e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1507e5c31af7Sopenharmony_ci			return 0;
1508e5c31af7Sopenharmony_ci	}
1509e5c31af7Sopenharmony_ci}
1510e5c31af7Sopenharmony_ci
1511e5c31af7Sopenharmony_cisglr::pdec::ShaderProgramDeclaration DrawTestShaderProgram::createProgramDeclaration (const glu::RenderContext& ctx, const std::vector<AttributeArray*>& arrays)
1512e5c31af7Sopenharmony_ci{
1513e5c31af7Sopenharmony_ci	sglr::pdec::ShaderProgramDeclaration decl;
1514e5c31af7Sopenharmony_ci
1515e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1516e5c31af7Sopenharmony_ci		decl << sglr::pdec::VertexAttribute(std::string("a_") + de::toString(arrayNdx), mapOutputType(arrays[arrayNdx]->getOutputType()));
1517e5c31af7Sopenharmony_ci
1518e5c31af7Sopenharmony_ci	decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
1519e5c31af7Sopenharmony_ci	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
1520e5c31af7Sopenharmony_ci
1521e5c31af7Sopenharmony_ci	decl << sglr::pdec::VertexSource(genVertexSource(ctx, arrays));
1522e5c31af7Sopenharmony_ci	decl << sglr::pdec::FragmentSource(genFragmentSource(ctx));
1523e5c31af7Sopenharmony_ci
1524e5c31af7Sopenharmony_ci	decl << sglr::pdec::Uniform("u_coordScale", glu::TYPE_FLOAT);
1525e5c31af7Sopenharmony_ci	decl << sglr::pdec::Uniform("u_colorScale", glu::TYPE_FLOAT);
1526e5c31af7Sopenharmony_ci
1527e5c31af7Sopenharmony_ci	return decl;
1528e5c31af7Sopenharmony_ci}
1529e5c31af7Sopenharmony_ci
1530e5c31af7Sopenharmony_ciclass RandomArrayGenerator
1531e5c31af7Sopenharmony_ci{
1532e5c31af7Sopenharmony_cipublic:
1533e5c31af7Sopenharmony_ci	static char*			generateArray			(int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type);
1534e5c31af7Sopenharmony_ci	static char*			generateIndices			(int seed, int elementCount, DrawTestSpec::IndexType type, int offset, int min, int max, int indexBase);
1535e5c31af7Sopenharmony_ci	static rr::GenericVec4	generateAttributeValue	(int seed, DrawTestSpec::InputType type);
1536e5c31af7Sopenharmony_ci
1537e5c31af7Sopenharmony_ciprivate:
1538e5c31af7Sopenharmony_ci	template<typename T>
1539e5c31af7Sopenharmony_ci	static char*			createIndices			(int seed, int elementCount, int offset, int min, int max, int indexBase);
1540e5c31af7Sopenharmony_ci
1541e5c31af7Sopenharmony_ci	static char*			generateBasicArray		(int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type);
1542e5c31af7Sopenharmony_ci	template<typename T, typename GLType>
1543e5c31af7Sopenharmony_ci	static char*			createBasicArray		(int seed, int elementCount, int componentCount, int offset, int stride);
1544e5c31af7Sopenharmony_ci	static char*			generatePackedArray		(int seed, int elementCount, int componentCount, int offset, int stride);
1545e5c31af7Sopenharmony_ci};
1546e5c31af7Sopenharmony_ci
1547e5c31af7Sopenharmony_cichar* RandomArrayGenerator::generateArray (int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type)
1548e5c31af7Sopenharmony_ci{
1549e5c31af7Sopenharmony_ci	if (type == DrawTestSpec::INPUTTYPE_INT_2_10_10_10 || type == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
1550e5c31af7Sopenharmony_ci		return generatePackedArray(seed, elementCount, componentCount, offset, stride);
1551e5c31af7Sopenharmony_ci	else
1552e5c31af7Sopenharmony_ci		return generateBasicArray(seed, elementCount, componentCount, offset, stride, type);
1553e5c31af7Sopenharmony_ci}
1554e5c31af7Sopenharmony_ci
1555e5c31af7Sopenharmony_cichar* RandomArrayGenerator::generateBasicArray (int seed, int elementCount, int componentCount, int offset, int stride, DrawTestSpec::InputType type)
1556e5c31af7Sopenharmony_ci{
1557e5c31af7Sopenharmony_ci	switch (type)
1558e5c31af7Sopenharmony_ci	{
1559e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_FLOAT:				return createBasicArray<float,		GLValue::Float>	(seed, elementCount, componentCount, offset, stride);
1560e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_DOUBLE:			return createBasicArray<double,		GLValue::Double>(seed, elementCount, componentCount, offset, stride);
1561e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_SHORT:				return createBasicArray<deInt16,	GLValue::Short>	(seed, elementCount, componentCount, offset, stride);
1562e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT:	return createBasicArray<deUint16,	GLValue::Ushort>(seed, elementCount, componentCount, offset, stride);
1563e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_BYTE:				return createBasicArray<deInt8,		GLValue::Byte>	(seed, elementCount, componentCount, offset, stride);
1564e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE:		return createBasicArray<deUint8,	GLValue::Ubyte>	(seed, elementCount, componentCount, offset, stride);
1565e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_FIXED:				return createBasicArray<deInt32,	GLValue::Fixed>	(seed, elementCount, componentCount, offset, stride);
1566e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_INT:				return createBasicArray<deInt32,	GLValue::Int>	(seed, elementCount, componentCount, offset, stride);
1567e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_UNSIGNED_INT:		return createBasicArray<deUint32,	GLValue::Uint>	(seed, elementCount, componentCount, offset, stride);
1568e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_HALF:				return createBasicArray<deFloat16,	GLValue::Half>	(seed, elementCount, componentCount, offset, stride);
1569e5c31af7Sopenharmony_ci		default:
1570e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1571e5c31af7Sopenharmony_ci			break;
1572e5c31af7Sopenharmony_ci	}
1573e5c31af7Sopenharmony_ci	return DE_NULL;
1574e5c31af7Sopenharmony_ci}
1575e5c31af7Sopenharmony_ci
1576e5c31af7Sopenharmony_ci#if (DE_COMPILER == DE_COMPILER_GCC) && (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
1577e5c31af7Sopenharmony_ci	// GCC 4.8/4.9 incorrectly emits array-bounds warning from createBasicArray()
1578e5c31af7Sopenharmony_ci#	define GCC_ARRAY_BOUNDS_FALSE_NEGATIVE 1
1579e5c31af7Sopenharmony_ci#endif
1580e5c31af7Sopenharmony_ci
1581e5c31af7Sopenharmony_ci#if defined(GCC_ARRAY_BOUNDS_FALSE_NEGATIVE)
1582e5c31af7Sopenharmony_ci#	pragma GCC diagnostic push
1583e5c31af7Sopenharmony_ci#	pragma GCC diagnostic ignored "-Warray-bounds"
1584e5c31af7Sopenharmony_ci#endif
1585e5c31af7Sopenharmony_ci
1586e5c31af7Sopenharmony_citemplate<typename T, typename GLType>
1587e5c31af7Sopenharmony_cichar* RandomArrayGenerator::createBasicArray (int seed, int elementCount, int componentCount, int offset, int stride)
1588e5c31af7Sopenharmony_ci{
1589e5c31af7Sopenharmony_ci	DE_ASSERT(componentCount >= 1 && componentCount <= 4);
1590e5c31af7Sopenharmony_ci
1591e5c31af7Sopenharmony_ci	const GLType min = extractGLValue<GLType>(GLValue::getMinValue(GLValueTypeTraits<GLType>::Type));
1592e5c31af7Sopenharmony_ci	const GLType max = extractGLValue<GLType>(GLValue::getMaxValue(GLValueTypeTraits<GLType>::Type));
1593e5c31af7Sopenharmony_ci
1594e5c31af7Sopenharmony_ci	const size_t componentSize	= sizeof(T);
1595e5c31af7Sopenharmony_ci	const size_t elementSize	= componentSize * componentCount;
1596e5c31af7Sopenharmony_ci	const size_t bufferSize		= offset + (elementCount - 1) * stride + elementSize;
1597e5c31af7Sopenharmony_ci
1598e5c31af7Sopenharmony_ci	char* data = new char[bufferSize];
1599e5c31af7Sopenharmony_ci	char* writePtr = data + offset;
1600e5c31af7Sopenharmony_ci
1601e5c31af7Sopenharmony_ci	GLType previousComponents[4];
1602e5c31af7Sopenharmony_ci
1603e5c31af7Sopenharmony_ci	deRandom rnd;
1604e5c31af7Sopenharmony_ci	deRandom_init(&rnd, seed);
1605e5c31af7Sopenharmony_ci
1606e5c31af7Sopenharmony_ci	for (int vertexNdx = 0; vertexNdx < elementCount; vertexNdx++)
1607e5c31af7Sopenharmony_ci	{
1608e5c31af7Sopenharmony_ci		GLType components[4];
1609e5c31af7Sopenharmony_ci
1610e5c31af7Sopenharmony_ci		for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1611e5c31af7Sopenharmony_ci		{
1612e5c31af7Sopenharmony_ci			components[componentNdx] = getRandom<GLType>(rnd, min, max);
1613e5c31af7Sopenharmony_ci
1614e5c31af7Sopenharmony_ci			// Try to not create vertex near previous
1615e5c31af7Sopenharmony_ci			if (vertexNdx != 0 && abs(components[componentNdx] - previousComponents[componentNdx]) < minValue<GLType>())
1616e5c31af7Sopenharmony_ci			{
1617e5c31af7Sopenharmony_ci				// Too close, try again (but only once)
1618e5c31af7Sopenharmony_ci				components[componentNdx] = getRandom<GLType>(rnd, min, max);
1619e5c31af7Sopenharmony_ci			}
1620e5c31af7Sopenharmony_ci		}
1621e5c31af7Sopenharmony_ci
1622e5c31af7Sopenharmony_ci		for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1623e5c31af7Sopenharmony_ci			previousComponents[componentNdx] = components[componentNdx];
1624e5c31af7Sopenharmony_ci
1625e5c31af7Sopenharmony_ci		for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1626e5c31af7Sopenharmony_ci			alignmentSafeAssignment(writePtr + componentNdx*componentSize, components[componentNdx].getValue());
1627e5c31af7Sopenharmony_ci
1628e5c31af7Sopenharmony_ci		writePtr += stride;
1629e5c31af7Sopenharmony_ci	}
1630e5c31af7Sopenharmony_ci
1631e5c31af7Sopenharmony_ci	return data;
1632e5c31af7Sopenharmony_ci}
1633e5c31af7Sopenharmony_ci
1634e5c31af7Sopenharmony_ci#if defined(GCC_ARRAY_BOUNDS_FALSE_NEGATIVE)
1635e5c31af7Sopenharmony_ci#	pragma GCC diagnostic pop
1636e5c31af7Sopenharmony_ci#endif
1637e5c31af7Sopenharmony_ci
1638e5c31af7Sopenharmony_cichar* RandomArrayGenerator::generatePackedArray (int seed, int elementCount, int componentCount, int offset, int stride)
1639e5c31af7Sopenharmony_ci{
1640e5c31af7Sopenharmony_ci	DE_ASSERT(componentCount == 4);
1641e5c31af7Sopenharmony_ci	DE_UNREF(componentCount);
1642e5c31af7Sopenharmony_ci
1643e5c31af7Sopenharmony_ci	const deUint32 limit10		= (1 << 10);
1644e5c31af7Sopenharmony_ci	const deUint32 limit2		= (1 << 2);
1645e5c31af7Sopenharmony_ci	const size_t elementSize	= 4;
1646e5c31af7Sopenharmony_ci	const size_t bufferSize		= offset + (elementCount - 1) * stride + elementSize;
1647e5c31af7Sopenharmony_ci
1648e5c31af7Sopenharmony_ci	char* data = new char[bufferSize];
1649e5c31af7Sopenharmony_ci	char* writePtr = data + offset;
1650e5c31af7Sopenharmony_ci
1651e5c31af7Sopenharmony_ci	deRandom rnd;
1652e5c31af7Sopenharmony_ci	deRandom_init(&rnd, seed);
1653e5c31af7Sopenharmony_ci
1654e5c31af7Sopenharmony_ci	for (int vertexNdx = 0; vertexNdx < elementCount; vertexNdx++)
1655e5c31af7Sopenharmony_ci	{
1656e5c31af7Sopenharmony_ci		const deUint32 x			= deRandom_getUint32(&rnd) % limit10;
1657e5c31af7Sopenharmony_ci		const deUint32 y			= deRandom_getUint32(&rnd) % limit10;
1658e5c31af7Sopenharmony_ci		const deUint32 z			= deRandom_getUint32(&rnd) % limit10;
1659e5c31af7Sopenharmony_ci		const deUint32 w			= deRandom_getUint32(&rnd) % limit2;
1660e5c31af7Sopenharmony_ci		const deUint32 packedValue	= (w << 30) | (z << 20) | (y << 10) | (x);
1661e5c31af7Sopenharmony_ci
1662e5c31af7Sopenharmony_ci		alignmentSafeAssignment(writePtr, packedValue);
1663e5c31af7Sopenharmony_ci		writePtr += stride;
1664e5c31af7Sopenharmony_ci	}
1665e5c31af7Sopenharmony_ci
1666e5c31af7Sopenharmony_ci	return data;
1667e5c31af7Sopenharmony_ci}
1668e5c31af7Sopenharmony_ci
1669e5c31af7Sopenharmony_cichar* RandomArrayGenerator::generateIndices (int seed, int elementCount, DrawTestSpec::IndexType type, int offset, int min, int max, int indexBase)
1670e5c31af7Sopenharmony_ci{
1671e5c31af7Sopenharmony_ci	char* data = DE_NULL;
1672e5c31af7Sopenharmony_ci
1673e5c31af7Sopenharmony_ci	switch (type)
1674e5c31af7Sopenharmony_ci	{
1675e5c31af7Sopenharmony_ci		case DrawTestSpec::INDEXTYPE_BYTE:
1676e5c31af7Sopenharmony_ci			data = createIndices<deUint8>(seed, elementCount, offset, min, max, indexBase);
1677e5c31af7Sopenharmony_ci			break;
1678e5c31af7Sopenharmony_ci
1679e5c31af7Sopenharmony_ci		case DrawTestSpec::INDEXTYPE_SHORT:
1680e5c31af7Sopenharmony_ci			data = createIndices<deUint16>(seed, elementCount, offset, min, max, indexBase);
1681e5c31af7Sopenharmony_ci			break;
1682e5c31af7Sopenharmony_ci
1683e5c31af7Sopenharmony_ci		case DrawTestSpec::INDEXTYPE_INT:
1684e5c31af7Sopenharmony_ci			data = createIndices<deUint32>(seed, elementCount, offset, min, max, indexBase);
1685e5c31af7Sopenharmony_ci			break;
1686e5c31af7Sopenharmony_ci
1687e5c31af7Sopenharmony_ci		default:
1688e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1689e5c31af7Sopenharmony_ci			break;
1690e5c31af7Sopenharmony_ci	}
1691e5c31af7Sopenharmony_ci
1692e5c31af7Sopenharmony_ci	return data;
1693e5c31af7Sopenharmony_ci}
1694e5c31af7Sopenharmony_ci
1695e5c31af7Sopenharmony_citemplate<typename T>
1696e5c31af7Sopenharmony_cichar* RandomArrayGenerator::createIndices (int seed, int elementCount, int offset, int min, int max, int indexBase)
1697e5c31af7Sopenharmony_ci{
1698e5c31af7Sopenharmony_ci	const size_t elementSize	= sizeof(T);
1699e5c31af7Sopenharmony_ci	const size_t bufferSize		= offset + elementCount * elementSize;
1700e5c31af7Sopenharmony_ci
1701e5c31af7Sopenharmony_ci	char* data = new char[bufferSize];
1702e5c31af7Sopenharmony_ci	char* writePtr = data + offset;
1703e5c31af7Sopenharmony_ci
1704e5c31af7Sopenharmony_ci	deUint32 oldNdx1 = deUint32(-1);
1705e5c31af7Sopenharmony_ci	deUint32 oldNdx2 = deUint32(-1);
1706e5c31af7Sopenharmony_ci
1707e5c31af7Sopenharmony_ci	deRandom rnd;
1708e5c31af7Sopenharmony_ci	deRandom_init(&rnd, seed);
1709e5c31af7Sopenharmony_ci
1710e5c31af7Sopenharmony_ci	DE_ASSERT(indexBase >= 0); // watch for underflows
1711e5c31af7Sopenharmony_ci
1712e5c31af7Sopenharmony_ci	if (min < 0 || (size_t)min > std::numeric_limits<T>::max() ||
1713e5c31af7Sopenharmony_ci		max < 0 || (size_t)max > std::numeric_limits<T>::max() ||
1714e5c31af7Sopenharmony_ci		min > max)
1715e5c31af7Sopenharmony_ci		DE_FATAL("Invalid range");
1716e5c31af7Sopenharmony_ci
1717e5c31af7Sopenharmony_ci	for (int elementNdx = 0; elementNdx < elementCount; ++elementNdx)
1718e5c31af7Sopenharmony_ci	{
1719e5c31af7Sopenharmony_ci		deUint32 ndx = getRandom(rnd, GLValue::Uint::create(min), GLValue::Uint::create(max)).getValue();
1720e5c31af7Sopenharmony_ci
1721e5c31af7Sopenharmony_ci		// Try not to generate same index as any of previous two. This prevents
1722e5c31af7Sopenharmony_ci		// generation of degenerate triangles and lines. If [min, max] is too
1723e5c31af7Sopenharmony_ci		// small this cannot be guaranteed.
1724e5c31af7Sopenharmony_ci
1725e5c31af7Sopenharmony_ci		if (ndx == oldNdx1)			++ndx;
1726e5c31af7Sopenharmony_ci		if (ndx > (deUint32)max)	ndx = min;
1727e5c31af7Sopenharmony_ci		if (ndx == oldNdx2)			++ndx;
1728e5c31af7Sopenharmony_ci		if (ndx > (deUint32)max)	ndx = min;
1729e5c31af7Sopenharmony_ci		if (ndx == oldNdx1)			++ndx;
1730e5c31af7Sopenharmony_ci		if (ndx > (deUint32)max)	ndx = min;
1731e5c31af7Sopenharmony_ci
1732e5c31af7Sopenharmony_ci		oldNdx2 = oldNdx1;
1733e5c31af7Sopenharmony_ci		oldNdx1 = ndx;
1734e5c31af7Sopenharmony_ci
1735e5c31af7Sopenharmony_ci		ndx += indexBase;
1736e5c31af7Sopenharmony_ci
1737e5c31af7Sopenharmony_ci		alignmentSafeAssignment<T>(writePtr + elementSize * elementNdx, T(ndx));
1738e5c31af7Sopenharmony_ci	}
1739e5c31af7Sopenharmony_ci
1740e5c31af7Sopenharmony_ci	return data;
1741e5c31af7Sopenharmony_ci}
1742e5c31af7Sopenharmony_ci
1743e5c31af7Sopenharmony_cirr::GenericVec4	RandomArrayGenerator::generateAttributeValue (int seed, DrawTestSpec::InputType type)
1744e5c31af7Sopenharmony_ci{
1745e5c31af7Sopenharmony_ci	de::Random random(seed);
1746e5c31af7Sopenharmony_ci
1747e5c31af7Sopenharmony_ci	switch (type)
1748e5c31af7Sopenharmony_ci	{
1749e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_FLOAT:
1750e5c31af7Sopenharmony_ci			return rr::GenericVec4(generateRandomVec4(random));
1751e5c31af7Sopenharmony_ci
1752e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_INT:
1753e5c31af7Sopenharmony_ci			return rr::GenericVec4(generateRandomIVec4(random));
1754e5c31af7Sopenharmony_ci
1755e5c31af7Sopenharmony_ci		case DrawTestSpec::INPUTTYPE_UNSIGNED_INT:
1756e5c31af7Sopenharmony_ci			return rr::GenericVec4(generateRandomUVec4(random));
1757e5c31af7Sopenharmony_ci
1758e5c31af7Sopenharmony_ci		default:
1759e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1760e5c31af7Sopenharmony_ci			return rr::GenericVec4(tcu::Vec4(1, 1, 1, 1));
1761e5c31af7Sopenharmony_ci	}
1762e5c31af7Sopenharmony_ci}
1763e5c31af7Sopenharmony_ci
1764e5c31af7Sopenharmony_ci} // anonymous
1765e5c31af7Sopenharmony_ci
1766e5c31af7Sopenharmony_ci// AttributePack
1767e5c31af7Sopenharmony_ci
1768e5c31af7Sopenharmony_ciclass AttributePack
1769e5c31af7Sopenharmony_ci{
1770e5c31af7Sopenharmony_cipublic:
1771e5c31af7Sopenharmony_ci
1772e5c31af7Sopenharmony_ci								AttributePack		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, sglr::Context& drawContext, const tcu::UVec2& screenSize, bool useVao, bool logEnabled);
1773e5c31af7Sopenharmony_ci								~AttributePack		(void);
1774e5c31af7Sopenharmony_ci
1775e5c31af7Sopenharmony_ci	AttributeArray*				getArray			(int i);
1776e5c31af7Sopenharmony_ci	int							getArrayCount		(void);
1777e5c31af7Sopenharmony_ci
1778e5c31af7Sopenharmony_ci	void						newArray			(DrawTestSpec::Storage storage);
1779e5c31af7Sopenharmony_ci	void						clearArrays			(void);
1780e5c31af7Sopenharmony_ci	void						updateProgram		(void);
1781e5c31af7Sopenharmony_ci
1782e5c31af7Sopenharmony_ci	void						render				(DrawTestSpec::Primitive primitive, DrawTestSpec::DrawMethod drawMethod, int firstVertex, int vertexCount, DrawTestSpec::IndexType indexType, const void* indexOffset, int rangeStart, int rangeEnd, int instanceCount, int indirectOffset, int baseVertex, float coordScale, float colorScale, AttributeArray* indexArray);
1783e5c31af7Sopenharmony_ci
1784e5c31af7Sopenharmony_ci	const tcu::Surface&			getSurface			(void) const { return m_screen; }
1785e5c31af7Sopenharmony_ciprivate:
1786e5c31af7Sopenharmony_ci	tcu::TestContext&			m_testCtx;
1787e5c31af7Sopenharmony_ci	glu::RenderContext&			m_renderCtx;
1788e5c31af7Sopenharmony_ci	sglr::Context&				m_ctx;
1789e5c31af7Sopenharmony_ci
1790e5c31af7Sopenharmony_ci	std::vector<AttributeArray*>m_arrays;
1791e5c31af7Sopenharmony_ci	sglr::ShaderProgram*		m_program;
1792e5c31af7Sopenharmony_ci	tcu::Surface				m_screen;
1793e5c31af7Sopenharmony_ci	const bool					m_useVao;
1794e5c31af7Sopenharmony_ci	const bool					m_logEnabled;
1795e5c31af7Sopenharmony_ci	deUint32					m_programID;
1796e5c31af7Sopenharmony_ci	deUint32					m_vaoID;
1797e5c31af7Sopenharmony_ci};
1798e5c31af7Sopenharmony_ci
1799e5c31af7Sopenharmony_ciAttributePack::AttributePack (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, sglr::Context& drawContext, const tcu::UVec2& screenSize, bool useVao, bool logEnabled)
1800e5c31af7Sopenharmony_ci	: m_testCtx		(testCtx)
1801e5c31af7Sopenharmony_ci	, m_renderCtx	(renderCtx)
1802e5c31af7Sopenharmony_ci	, m_ctx			(drawContext)
1803e5c31af7Sopenharmony_ci	, m_program		(DE_NULL)
1804e5c31af7Sopenharmony_ci	, m_screen		(screenSize.x(), screenSize.y())
1805e5c31af7Sopenharmony_ci	, m_useVao		(useVao)
1806e5c31af7Sopenharmony_ci	, m_logEnabled	(logEnabled)
1807e5c31af7Sopenharmony_ci	, m_programID	(0)
1808e5c31af7Sopenharmony_ci	, m_vaoID		(0)
1809e5c31af7Sopenharmony_ci{
1810e5c31af7Sopenharmony_ci	if (m_useVao)
1811e5c31af7Sopenharmony_ci		m_ctx.genVertexArrays(1, &m_vaoID);
1812e5c31af7Sopenharmony_ci}
1813e5c31af7Sopenharmony_ci
1814e5c31af7Sopenharmony_ciAttributePack::~AttributePack (void)
1815e5c31af7Sopenharmony_ci{
1816e5c31af7Sopenharmony_ci	clearArrays();
1817e5c31af7Sopenharmony_ci
1818e5c31af7Sopenharmony_ci	if (m_programID)
1819e5c31af7Sopenharmony_ci		m_ctx.deleteProgram(m_programID);
1820e5c31af7Sopenharmony_ci
1821e5c31af7Sopenharmony_ci	if (m_program)
1822e5c31af7Sopenharmony_ci		delete m_program;
1823e5c31af7Sopenharmony_ci
1824e5c31af7Sopenharmony_ci	if (m_useVao)
1825e5c31af7Sopenharmony_ci		m_ctx.deleteVertexArrays(1, &m_vaoID);
1826e5c31af7Sopenharmony_ci}
1827e5c31af7Sopenharmony_ci
1828e5c31af7Sopenharmony_ciAttributeArray* AttributePack::getArray (int i)
1829e5c31af7Sopenharmony_ci{
1830e5c31af7Sopenharmony_ci	return m_arrays.at(i);
1831e5c31af7Sopenharmony_ci}
1832e5c31af7Sopenharmony_ci
1833e5c31af7Sopenharmony_ciint AttributePack::getArrayCount (void)
1834e5c31af7Sopenharmony_ci{
1835e5c31af7Sopenharmony_ci	return (int)m_arrays.size();
1836e5c31af7Sopenharmony_ci}
1837e5c31af7Sopenharmony_ci
1838e5c31af7Sopenharmony_civoid AttributePack::newArray (DrawTestSpec::Storage storage)
1839e5c31af7Sopenharmony_ci{
1840e5c31af7Sopenharmony_ci	m_arrays.push_back(new AttributeArray(storage, m_ctx));
1841e5c31af7Sopenharmony_ci}
1842e5c31af7Sopenharmony_ci
1843e5c31af7Sopenharmony_civoid AttributePack::clearArrays (void)
1844e5c31af7Sopenharmony_ci{
1845e5c31af7Sopenharmony_ci	for (std::vector<AttributeArray*>::iterator itr = m_arrays.begin(); itr != m_arrays.end(); itr++)
1846e5c31af7Sopenharmony_ci		delete *itr;
1847e5c31af7Sopenharmony_ci	m_arrays.clear();
1848e5c31af7Sopenharmony_ci}
1849e5c31af7Sopenharmony_ci
1850e5c31af7Sopenharmony_civoid AttributePack::updateProgram (void)
1851e5c31af7Sopenharmony_ci{
1852e5c31af7Sopenharmony_ci	if (m_programID)
1853e5c31af7Sopenharmony_ci		m_ctx.deleteProgram(m_programID);
1854e5c31af7Sopenharmony_ci	if (m_program)
1855e5c31af7Sopenharmony_ci		delete m_program;
1856e5c31af7Sopenharmony_ci
1857e5c31af7Sopenharmony_ci	m_program = new DrawTestShaderProgram(m_renderCtx, m_arrays);
1858e5c31af7Sopenharmony_ci	m_programID = m_ctx.createProgram(m_program);
1859e5c31af7Sopenharmony_ci}
1860e5c31af7Sopenharmony_ci
1861e5c31af7Sopenharmony_civoid AttributePack::render (DrawTestSpec::Primitive primitive, DrawTestSpec::DrawMethod drawMethod, int firstVertex, int vertexCount, DrawTestSpec::IndexType indexType, const void* indexOffset, int rangeStart, int rangeEnd, int instanceCount, int indirectOffset, int baseVertex, float coordScale, float colorScale, AttributeArray* indexArray)
1862e5c31af7Sopenharmony_ci{
1863e5c31af7Sopenharmony_ci	DE_ASSERT(m_program != DE_NULL);
1864e5c31af7Sopenharmony_ci	DE_ASSERT(m_programID != 0);
1865e5c31af7Sopenharmony_ci
1866e5c31af7Sopenharmony_ci	m_ctx.viewport(0, 0, m_screen.getWidth(), m_screen.getHeight());
1867e5c31af7Sopenharmony_ci	m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
1868e5c31af7Sopenharmony_ci	m_ctx.clear(GL_COLOR_BUFFER_BIT);
1869e5c31af7Sopenharmony_ci
1870e5c31af7Sopenharmony_ci	m_ctx.useProgram(m_programID);
1871e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glUseProgram()");
1872e5c31af7Sopenharmony_ci
1873e5c31af7Sopenharmony_ci	m_ctx.uniform1f(m_ctx.getUniformLocation(m_programID, "u_coordScale"), coordScale);
1874e5c31af7Sopenharmony_ci	m_ctx.uniform1f(m_ctx.getUniformLocation(m_programID, "u_colorScale"), colorScale);
1875e5c31af7Sopenharmony_ci
1876e5c31af7Sopenharmony_ci	if (m_useVao)
1877e5c31af7Sopenharmony_ci		m_ctx.bindVertexArray(m_vaoID);
1878e5c31af7Sopenharmony_ci
1879e5c31af7Sopenharmony_ci	if (indexArray)
1880e5c31af7Sopenharmony_ci		indexArray->bindIndexArray(DrawTestSpec::TARGET_ELEMENT_ARRAY);
1881e5c31af7Sopenharmony_ci
1882e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
1883e5c31af7Sopenharmony_ci	{
1884e5c31af7Sopenharmony_ci		std::stringstream attribName;
1885e5c31af7Sopenharmony_ci		attribName << "a_" << arrayNdx;
1886e5c31af7Sopenharmony_ci
1887e5c31af7Sopenharmony_ci		deUint32 loc = m_ctx.getAttribLocation(m_programID, attribName.str().c_str());
1888e5c31af7Sopenharmony_ci
1889e5c31af7Sopenharmony_ci		if (m_arrays[arrayNdx]->isBound())
1890e5c31af7Sopenharmony_ci		{
1891e5c31af7Sopenharmony_ci			m_ctx.enableVertexAttribArray(loc);
1892e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glEnableVertexAttribArray()");
1893e5c31af7Sopenharmony_ci		}
1894e5c31af7Sopenharmony_ci
1895e5c31af7Sopenharmony_ci		m_arrays[arrayNdx]->bindAttribute(loc);
1896e5c31af7Sopenharmony_ci	}
1897e5c31af7Sopenharmony_ci
1898e5c31af7Sopenharmony_ci	if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWARRAYS)
1899e5c31af7Sopenharmony_ci	{
1900e5c31af7Sopenharmony_ci		m_ctx.drawArrays(primitiveToGL(primitive), firstVertex, vertexCount);
1901e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArrays()");
1902e5c31af7Sopenharmony_ci	}
1903e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED)
1904e5c31af7Sopenharmony_ci	{
1905e5c31af7Sopenharmony_ci		m_ctx.drawArraysInstanced(primitiveToGL(primitive), firstVertex, vertexCount, instanceCount);
1906e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArraysInstanced()");
1907e5c31af7Sopenharmony_ci	}
1908e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS)
1909e5c31af7Sopenharmony_ci	{
1910e5c31af7Sopenharmony_ci		m_ctx.drawElements(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset);
1911e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElements()");
1912e5c31af7Sopenharmony_ci	}
1913e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
1914e5c31af7Sopenharmony_ci	{
1915e5c31af7Sopenharmony_ci		m_ctx.drawRangeElements(primitiveToGL(primitive), rangeStart, rangeEnd, vertexCount, indexTypeToGL(indexType), indexOffset);
1916e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawRangeElements()");
1917e5c31af7Sopenharmony_ci	}
1918e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED)
1919e5c31af7Sopenharmony_ci	{
1920e5c31af7Sopenharmony_ci		m_ctx.drawElementsInstanced(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset, instanceCount);
1921e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElementsInstanced()");
1922e5c31af7Sopenharmony_ci	}
1923e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT)
1924e5c31af7Sopenharmony_ci	{
1925e5c31af7Sopenharmony_ci		struct DrawCommand
1926e5c31af7Sopenharmony_ci		{
1927e5c31af7Sopenharmony_ci			GLuint count;
1928e5c31af7Sopenharmony_ci			GLuint primCount;
1929e5c31af7Sopenharmony_ci			GLuint first;
1930e5c31af7Sopenharmony_ci			GLuint reservedMustBeZero;
1931e5c31af7Sopenharmony_ci		};
1932e5c31af7Sopenharmony_ci		deUint8* buffer = new deUint8[sizeof(DrawCommand) + indirectOffset];
1933e5c31af7Sopenharmony_ci
1934e5c31af7Sopenharmony_ci		{
1935e5c31af7Sopenharmony_ci			DrawCommand command;
1936e5c31af7Sopenharmony_ci
1937e5c31af7Sopenharmony_ci			command.count				= vertexCount;
1938e5c31af7Sopenharmony_ci			command.primCount			= instanceCount;
1939e5c31af7Sopenharmony_ci			command.first				= firstVertex;
1940e5c31af7Sopenharmony_ci			command.reservedMustBeZero	= 0;
1941e5c31af7Sopenharmony_ci
1942e5c31af7Sopenharmony_ci			memcpy(buffer + indirectOffset, &command, sizeof(command));
1943e5c31af7Sopenharmony_ci
1944e5c31af7Sopenharmony_ci			if (m_logEnabled)
1945e5c31af7Sopenharmony_ci				m_testCtx.getLog()
1946e5c31af7Sopenharmony_ci					<< tcu::TestLog::Message
1947e5c31af7Sopenharmony_ci					<< "DrawArraysIndirectCommand:\n"
1948e5c31af7Sopenharmony_ci					<< "\tcount: " << command.count << "\n"
1949e5c31af7Sopenharmony_ci					<< "\tprimCount: " << command.primCount << "\n"
1950e5c31af7Sopenharmony_ci					<< "\tfirst: " << command.first << "\n"
1951e5c31af7Sopenharmony_ci					<< "\treservedMustBeZero: " << command.reservedMustBeZero << "\n"
1952e5c31af7Sopenharmony_ci					<< tcu::TestLog::EndMessage;
1953e5c31af7Sopenharmony_ci		}
1954e5c31af7Sopenharmony_ci
1955e5c31af7Sopenharmony_ci		GLuint indirectBuf = 0;
1956e5c31af7Sopenharmony_ci		m_ctx.genBuffers(1, &indirectBuf);
1957e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuf);
1958e5c31af7Sopenharmony_ci		m_ctx.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand) + indirectOffset, buffer, GL_STATIC_DRAW);
1959e5c31af7Sopenharmony_ci		delete [] buffer;
1960e5c31af7Sopenharmony_ci
1961e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "Setup draw indirect buffer");
1962e5c31af7Sopenharmony_ci
1963e5c31af7Sopenharmony_ci		m_ctx.drawArraysIndirect(primitiveToGL(primitive), glu::BufferOffsetAsPointer(indirectOffset));
1964e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArraysIndirect()");
1965e5c31af7Sopenharmony_ci
1966e5c31af7Sopenharmony_ci		m_ctx.deleteBuffers(1, &indirectBuf);
1967e5c31af7Sopenharmony_ci	}
1968e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT)
1969e5c31af7Sopenharmony_ci	{
1970e5c31af7Sopenharmony_ci		struct DrawCommand
1971e5c31af7Sopenharmony_ci		{
1972e5c31af7Sopenharmony_ci			GLuint count;
1973e5c31af7Sopenharmony_ci			GLuint primCount;
1974e5c31af7Sopenharmony_ci			GLuint firstIndex;
1975e5c31af7Sopenharmony_ci			GLint  baseVertex;
1976e5c31af7Sopenharmony_ci			GLuint reservedMustBeZero;
1977e5c31af7Sopenharmony_ci		};
1978e5c31af7Sopenharmony_ci		deUint8* buffer = new deUint8[sizeof(DrawCommand) + indirectOffset];
1979e5c31af7Sopenharmony_ci
1980e5c31af7Sopenharmony_ci		{
1981e5c31af7Sopenharmony_ci			DrawCommand command;
1982e5c31af7Sopenharmony_ci
1983e5c31af7Sopenharmony_ci			// index offset must be converted to firstIndex by dividing with the index element size
1984e5c31af7Sopenharmony_ci			const auto offsetAsInteger = reinterpret_cast<uintptr_t>(indexOffset);
1985e5c31af7Sopenharmony_ci			DE_ASSERT(offsetAsInteger % gls::DrawTestSpec::indexTypeSize(indexType) == 0); // \note This is checked in spec validation
1986e5c31af7Sopenharmony_ci
1987e5c31af7Sopenharmony_ci			command.count				= vertexCount;
1988e5c31af7Sopenharmony_ci			command.primCount			= instanceCount;
1989e5c31af7Sopenharmony_ci			command.firstIndex			= (glw::GLuint)(offsetAsInteger / gls::DrawTestSpec::indexTypeSize(indexType));
1990e5c31af7Sopenharmony_ci			command.baseVertex			= baseVertex;
1991e5c31af7Sopenharmony_ci			command.reservedMustBeZero	= 0;
1992e5c31af7Sopenharmony_ci
1993e5c31af7Sopenharmony_ci			memcpy(buffer + indirectOffset, &command, sizeof(command));
1994e5c31af7Sopenharmony_ci
1995e5c31af7Sopenharmony_ci			if (m_logEnabled)
1996e5c31af7Sopenharmony_ci				m_testCtx.getLog()
1997e5c31af7Sopenharmony_ci					<< tcu::TestLog::Message
1998e5c31af7Sopenharmony_ci					<< "DrawElementsIndirectCommand:\n"
1999e5c31af7Sopenharmony_ci					<< "\tcount: " << command.count << "\n"
2000e5c31af7Sopenharmony_ci					<< "\tprimCount: " << command.primCount << "\n"
2001e5c31af7Sopenharmony_ci					<< "\tfirstIndex: " << command.firstIndex << "\n"
2002e5c31af7Sopenharmony_ci					<< "\tbaseVertex: " << command.baseVertex << "\n"
2003e5c31af7Sopenharmony_ci					<< "\treservedMustBeZero: " << command.reservedMustBeZero << "\n"
2004e5c31af7Sopenharmony_ci					<< tcu::TestLog::EndMessage;
2005e5c31af7Sopenharmony_ci		}
2006e5c31af7Sopenharmony_ci
2007e5c31af7Sopenharmony_ci		GLuint indirectBuf = 0;
2008e5c31af7Sopenharmony_ci		m_ctx.genBuffers(1, &indirectBuf);
2009e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(GL_DRAW_INDIRECT_BUFFER, indirectBuf);
2010e5c31af7Sopenharmony_ci		m_ctx.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(DrawCommand) + indirectOffset, buffer, GL_STATIC_DRAW);
2011e5c31af7Sopenharmony_ci		delete [] buffer;
2012e5c31af7Sopenharmony_ci
2013e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "Setup draw indirect buffer");
2014e5c31af7Sopenharmony_ci
2015e5c31af7Sopenharmony_ci		m_ctx.drawElementsIndirect(primitiveToGL(primitive), indexTypeToGL(indexType), glu::BufferOffsetAsPointer(indirectOffset));
2016e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArraysIndirect()");
2017e5c31af7Sopenharmony_ci
2018e5c31af7Sopenharmony_ci		m_ctx.deleteBuffers(1, &indirectBuf);
2019e5c31af7Sopenharmony_ci	}
2020e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
2021e5c31af7Sopenharmony_ci	{
2022e5c31af7Sopenharmony_ci		m_ctx.drawElementsBaseVertex(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset, baseVertex);
2023e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElementsBaseVertex()");
2024e5c31af7Sopenharmony_ci	}
2025e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX)
2026e5c31af7Sopenharmony_ci	{
2027e5c31af7Sopenharmony_ci		m_ctx.drawElementsInstancedBaseVertex(primitiveToGL(primitive), vertexCount, indexTypeToGL(indexType), indexOffset, instanceCount, baseVertex);
2028e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawElementsInstancedBaseVertex()");
2029e5c31af7Sopenharmony_ci	}
2030e5c31af7Sopenharmony_ci	else if (drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
2031e5c31af7Sopenharmony_ci	{
2032e5c31af7Sopenharmony_ci		m_ctx.drawRangeElementsBaseVertex(primitiveToGL(primitive), rangeStart, rangeEnd, vertexCount, indexTypeToGL(indexType), indexOffset, baseVertex);
2033e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawRangeElementsBaseVertex()");
2034e5c31af7Sopenharmony_ci	}
2035e5c31af7Sopenharmony_ci	else
2036e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
2037e5c31af7Sopenharmony_ci
2038e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
2039e5c31af7Sopenharmony_ci	{
2040e5c31af7Sopenharmony_ci		if (m_arrays[arrayNdx]->isBound())
2041e5c31af7Sopenharmony_ci		{
2042e5c31af7Sopenharmony_ci			std::stringstream attribName;
2043e5c31af7Sopenharmony_ci			attribName << "a_" << arrayNdx;
2044e5c31af7Sopenharmony_ci
2045e5c31af7Sopenharmony_ci			deUint32 loc = m_ctx.getAttribLocation(m_programID, attribName.str().c_str());
2046e5c31af7Sopenharmony_ci
2047e5c31af7Sopenharmony_ci			m_ctx.disableVertexAttribArray(loc);
2048e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDisableVertexAttribArray()");
2049e5c31af7Sopenharmony_ci		}
2050e5c31af7Sopenharmony_ci	}
2051e5c31af7Sopenharmony_ci
2052e5c31af7Sopenharmony_ci	if (m_useVao)
2053e5c31af7Sopenharmony_ci		m_ctx.bindVertexArray(0);
2054e5c31af7Sopenharmony_ci
2055e5c31af7Sopenharmony_ci	m_ctx.useProgram(0);
2056e5c31af7Sopenharmony_ci	m_ctx.readPixels(m_screen, 0, 0, m_screen.getWidth(), m_screen.getHeight());
2057e5c31af7Sopenharmony_ci}
2058e5c31af7Sopenharmony_ci
2059e5c31af7Sopenharmony_ci// DrawTestSpec
2060e5c31af7Sopenharmony_ci
2061e5c31af7Sopenharmony_ciDrawTestSpec::AttributeSpec	DrawTestSpec::AttributeSpec::createAttributeArray (InputType inputType, OutputType outputType, Storage storage, Usage usage, int componentCount, int offset, int stride, bool normalize, int instanceDivisor)
2062e5c31af7Sopenharmony_ci{
2063e5c31af7Sopenharmony_ci	DrawTestSpec::AttributeSpec spec;
2064e5c31af7Sopenharmony_ci
2065e5c31af7Sopenharmony_ci	spec.inputType			= inputType;
2066e5c31af7Sopenharmony_ci	spec.outputType			= outputType;
2067e5c31af7Sopenharmony_ci	spec.storage			= storage;
2068e5c31af7Sopenharmony_ci	spec.usage				= usage;
2069e5c31af7Sopenharmony_ci	spec.componentCount		= componentCount;
2070e5c31af7Sopenharmony_ci	spec.offset				= offset;
2071e5c31af7Sopenharmony_ci	spec.stride				= stride;
2072e5c31af7Sopenharmony_ci	spec.normalize			= normalize;
2073e5c31af7Sopenharmony_ci	spec.instanceDivisor	= instanceDivisor;
2074e5c31af7Sopenharmony_ci
2075e5c31af7Sopenharmony_ci	spec.useDefaultAttribute= false;
2076e5c31af7Sopenharmony_ci
2077e5c31af7Sopenharmony_ci	return spec;
2078e5c31af7Sopenharmony_ci}
2079e5c31af7Sopenharmony_ci
2080e5c31af7Sopenharmony_ciDrawTestSpec::AttributeSpec	DrawTestSpec::AttributeSpec::createDefaultAttribute (InputType inputType, OutputType outputType, int componentCount)
2081e5c31af7Sopenharmony_ci{
2082e5c31af7Sopenharmony_ci	DE_ASSERT(inputType == INPUTTYPE_INT || inputType == INPUTTYPE_UNSIGNED_INT || inputType == INPUTTYPE_FLOAT);
2083e5c31af7Sopenharmony_ci	DE_ASSERT(inputType == INPUTTYPE_FLOAT || componentCount == 4);
2084e5c31af7Sopenharmony_ci
2085e5c31af7Sopenharmony_ci	DrawTestSpec::AttributeSpec spec;
2086e5c31af7Sopenharmony_ci
2087e5c31af7Sopenharmony_ci	spec.inputType				= inputType;
2088e5c31af7Sopenharmony_ci	spec.outputType				= outputType;
2089e5c31af7Sopenharmony_ci	spec.storage				= DrawTestSpec::STORAGE_LAST;
2090e5c31af7Sopenharmony_ci	spec.usage					= DrawTestSpec::USAGE_LAST;
2091e5c31af7Sopenharmony_ci	spec.componentCount			= componentCount;
2092e5c31af7Sopenharmony_ci	spec.offset					= 0;
2093e5c31af7Sopenharmony_ci	spec.stride					= 0;
2094e5c31af7Sopenharmony_ci	spec.normalize				= 0;
2095e5c31af7Sopenharmony_ci	spec.instanceDivisor		= 0;
2096e5c31af7Sopenharmony_ci
2097e5c31af7Sopenharmony_ci	spec.useDefaultAttribute	= true;
2098e5c31af7Sopenharmony_ci
2099e5c31af7Sopenharmony_ci	return spec;
2100e5c31af7Sopenharmony_ci}
2101e5c31af7Sopenharmony_ci
2102e5c31af7Sopenharmony_ciDrawTestSpec::AttributeSpec::AttributeSpec (void)
2103e5c31af7Sopenharmony_ci{
2104e5c31af7Sopenharmony_ci	inputType					= DrawTestSpec::INPUTTYPE_LAST;
2105e5c31af7Sopenharmony_ci	outputType					= DrawTestSpec::OUTPUTTYPE_LAST;
2106e5c31af7Sopenharmony_ci	storage						= DrawTestSpec::STORAGE_LAST;
2107e5c31af7Sopenharmony_ci	usage						= DrawTestSpec::USAGE_LAST;
2108e5c31af7Sopenharmony_ci	componentCount				= 0;
2109e5c31af7Sopenharmony_ci	offset						= 0;
2110e5c31af7Sopenharmony_ci	stride						= 0;
2111e5c31af7Sopenharmony_ci	normalize					= false;
2112e5c31af7Sopenharmony_ci	instanceDivisor				= 0;
2113e5c31af7Sopenharmony_ci	useDefaultAttribute			= false;
2114e5c31af7Sopenharmony_ci	additionalPositionAttribute = false;
2115e5c31af7Sopenharmony_ci	bgraComponentOrder			= false;
2116e5c31af7Sopenharmony_ci}
2117e5c31af7Sopenharmony_ci
2118e5c31af7Sopenharmony_ciint DrawTestSpec::AttributeSpec::hash (void) const
2119e5c31af7Sopenharmony_ci{
2120e5c31af7Sopenharmony_ci	if (useDefaultAttribute)
2121e5c31af7Sopenharmony_ci	{
2122e5c31af7Sopenharmony_ci		return 1 * int(inputType) + 7 * int(outputType) + 13 * componentCount;
2123e5c31af7Sopenharmony_ci	}
2124e5c31af7Sopenharmony_ci	else
2125e5c31af7Sopenharmony_ci	{
2126e5c31af7Sopenharmony_ci		return 1 * int(inputType) + 2 * int(outputType) + 3 * int(storage) + 5 * int(usage) + 7 * componentCount + 11 * offset + 13 * stride + 17 * (normalize ? 0 : 1) + 19 * instanceDivisor;
2127e5c31af7Sopenharmony_ci	}
2128e5c31af7Sopenharmony_ci}
2129e5c31af7Sopenharmony_ci
2130e5c31af7Sopenharmony_cibool DrawTestSpec::AttributeSpec::valid (glu::ApiType ctxType) const
2131e5c31af7Sopenharmony_ci{
2132e5c31af7Sopenharmony_ci	const bool inputTypeFloat				= inputType == DrawTestSpec::INPUTTYPE_FLOAT || inputType  == DrawTestSpec::INPUTTYPE_FIXED || inputType == DrawTestSpec::INPUTTYPE_HALF;
2133e5c31af7Sopenharmony_ci	const bool inputTypeUnsignedInteger		= inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE || inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT || inputType  == DrawTestSpec::INPUTTYPE_UNSIGNED_INT || inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10;
2134e5c31af7Sopenharmony_ci	const bool inputTypeSignedInteger		= inputType == DrawTestSpec::INPUTTYPE_BYTE  || inputType == DrawTestSpec::INPUTTYPE_SHORT || inputType == DrawTestSpec::INPUTTYPE_INT || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2135e5c31af7Sopenharmony_ci	const bool inputTypePacked				= inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2136e5c31af7Sopenharmony_ci
2137e5c31af7Sopenharmony_ci	const bool outputTypeFloat				= outputType == DrawTestSpec::OUTPUTTYPE_FLOAT || outputType == DrawTestSpec::OUTPUTTYPE_VEC2  || outputType == DrawTestSpec::OUTPUTTYPE_VEC3  || outputType == DrawTestSpec::OUTPUTTYPE_VEC4;
2138e5c31af7Sopenharmony_ci	const bool outputTypeSignedInteger		= outputType == DrawTestSpec::OUTPUTTYPE_INT   || outputType == DrawTestSpec::OUTPUTTYPE_IVEC2 || outputType == DrawTestSpec::OUTPUTTYPE_IVEC3 || outputType == DrawTestSpec::OUTPUTTYPE_IVEC4;
2139e5c31af7Sopenharmony_ci	const bool outputTypeUnsignedInteger	= outputType == DrawTestSpec::OUTPUTTYPE_UINT  || outputType == DrawTestSpec::OUTPUTTYPE_UVEC2 || outputType == DrawTestSpec::OUTPUTTYPE_UVEC3 || outputType == DrawTestSpec::OUTPUTTYPE_UVEC4;
2140e5c31af7Sopenharmony_ci
2141e5c31af7Sopenharmony_ci	if (useDefaultAttribute)
2142e5c31af7Sopenharmony_ci	{
2143e5c31af7Sopenharmony_ci		if (inputType != DrawTestSpec::INPUTTYPE_INT && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_INT && inputType != DrawTestSpec::INPUTTYPE_FLOAT)
2144e5c31af7Sopenharmony_ci			return false;
2145e5c31af7Sopenharmony_ci
2146e5c31af7Sopenharmony_ci		if (inputType != DrawTestSpec::INPUTTYPE_FLOAT && componentCount != 4)
2147e5c31af7Sopenharmony_ci			return false;
2148e5c31af7Sopenharmony_ci
2149e5c31af7Sopenharmony_ci		// no casting allowed (undefined results)
2150e5c31af7Sopenharmony_ci		if (inputType == DrawTestSpec::INPUTTYPE_INT && !outputTypeSignedInteger)
2151e5c31af7Sopenharmony_ci			return false;
2152e5c31af7Sopenharmony_ci		if (inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT && !outputTypeUnsignedInteger)
2153e5c31af7Sopenharmony_ci			return false;
2154e5c31af7Sopenharmony_ci	}
2155e5c31af7Sopenharmony_ci
2156e5c31af7Sopenharmony_ci	if (inputTypePacked && componentCount != 4)
2157e5c31af7Sopenharmony_ci		return false;
2158e5c31af7Sopenharmony_ci
2159e5c31af7Sopenharmony_ci	// Invalid conversions:
2160e5c31af7Sopenharmony_ci
2161e5c31af7Sopenharmony_ci	// float -> [u]int
2162e5c31af7Sopenharmony_ci	if (inputTypeFloat && !outputTypeFloat)
2163e5c31af7Sopenharmony_ci		return false;
2164e5c31af7Sopenharmony_ci
2165e5c31af7Sopenharmony_ci	// uint -> int		(undefined results)
2166e5c31af7Sopenharmony_ci	if (inputTypeUnsignedInteger && outputTypeSignedInteger)
2167e5c31af7Sopenharmony_ci		return false;
2168e5c31af7Sopenharmony_ci
2169e5c31af7Sopenharmony_ci	// int -> uint		(undefined results)
2170e5c31af7Sopenharmony_ci	if (inputTypeSignedInteger && outputTypeUnsignedInteger)
2171e5c31af7Sopenharmony_ci		return false;
2172e5c31af7Sopenharmony_ci
2173e5c31af7Sopenharmony_ci	// packed -> non-float (packed formats are converted to floats)
2174e5c31af7Sopenharmony_ci	if (inputTypePacked && !outputTypeFloat)
2175e5c31af7Sopenharmony_ci		return false;
2176e5c31af7Sopenharmony_ci
2177e5c31af7Sopenharmony_ci	// Invalid normalize. Normalize is only valid if output type is float
2178e5c31af7Sopenharmony_ci	if (normalize && !outputTypeFloat)
2179e5c31af7Sopenharmony_ci		return false;
2180e5c31af7Sopenharmony_ci
2181e5c31af7Sopenharmony_ci	// Allow reverse order (GL_BGRA) only for packed and 4-component ubyte
2182e5c31af7Sopenharmony_ci	if (bgraComponentOrder && componentCount != 4)
2183e5c31af7Sopenharmony_ci		return false;
2184e5c31af7Sopenharmony_ci	if (bgraComponentOrder && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 && inputType != DrawTestSpec::INPUTTYPE_INT_2_10_10_10 && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE)
2185e5c31af7Sopenharmony_ci		return false;
2186e5c31af7Sopenharmony_ci	if (bgraComponentOrder && normalize != true)
2187e5c31af7Sopenharmony_ci		return false;
2188e5c31af7Sopenharmony_ci
2189e5c31af7Sopenharmony_ci	// GLES2 limits
2190e5c31af7Sopenharmony_ci	if (ctxType == glu::ApiType::es(2,0))
2191e5c31af7Sopenharmony_ci	{
2192e5c31af7Sopenharmony_ci		if (inputType != DrawTestSpec::INPUTTYPE_FLOAT && inputType != DrawTestSpec::INPUTTYPE_FIXED &&
2193e5c31af7Sopenharmony_ci			inputType != DrawTestSpec::INPUTTYPE_BYTE  && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE &&
2194e5c31af7Sopenharmony_ci			inputType != DrawTestSpec::INPUTTYPE_SHORT && inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT)
2195e5c31af7Sopenharmony_ci			return false;
2196e5c31af7Sopenharmony_ci
2197e5c31af7Sopenharmony_ci		if (!outputTypeFloat)
2198e5c31af7Sopenharmony_ci			return false;
2199e5c31af7Sopenharmony_ci
2200e5c31af7Sopenharmony_ci		if (bgraComponentOrder)
2201e5c31af7Sopenharmony_ci			return false;
2202e5c31af7Sopenharmony_ci	}
2203e5c31af7Sopenharmony_ci
2204e5c31af7Sopenharmony_ci	// GLES3 limits
2205e5c31af7Sopenharmony_ci	if (ctxType.getProfile() == glu::PROFILE_ES && ctxType.getMajorVersion() == 3)
2206e5c31af7Sopenharmony_ci	{
2207e5c31af7Sopenharmony_ci		if (bgraComponentOrder)
2208e5c31af7Sopenharmony_ci			return false;
2209e5c31af7Sopenharmony_ci	}
2210e5c31af7Sopenharmony_ci
2211e5c31af7Sopenharmony_ci	// No user pointers in GL core
2212e5c31af7Sopenharmony_ci	if (ctxType.getProfile() == glu::PROFILE_CORE)
2213e5c31af7Sopenharmony_ci	{
2214e5c31af7Sopenharmony_ci		if (!useDefaultAttribute && storage == DrawTestSpec::STORAGE_USER)
2215e5c31af7Sopenharmony_ci			return false;
2216e5c31af7Sopenharmony_ci	}
2217e5c31af7Sopenharmony_ci
2218e5c31af7Sopenharmony_ci	return true;
2219e5c31af7Sopenharmony_ci}
2220e5c31af7Sopenharmony_ci
2221e5c31af7Sopenharmony_cibool DrawTestSpec::AttributeSpec::isBufferAligned (void) const
2222e5c31af7Sopenharmony_ci{
2223e5c31af7Sopenharmony_ci	const bool inputTypePacked = inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2224e5c31af7Sopenharmony_ci
2225e5c31af7Sopenharmony_ci	// Buffer alignment, offset is a multiple of underlying data type size?
2226e5c31af7Sopenharmony_ci	if (storage == STORAGE_BUFFER)
2227e5c31af7Sopenharmony_ci	{
2228e5c31af7Sopenharmony_ci		int dataTypeSize = gls::DrawTestSpec::inputTypeSize(inputType);
2229e5c31af7Sopenharmony_ci		if (inputTypePacked)
2230e5c31af7Sopenharmony_ci			dataTypeSize = 4;
2231e5c31af7Sopenharmony_ci
2232e5c31af7Sopenharmony_ci		if (offset % dataTypeSize != 0)
2233e5c31af7Sopenharmony_ci			return false;
2234e5c31af7Sopenharmony_ci	}
2235e5c31af7Sopenharmony_ci
2236e5c31af7Sopenharmony_ci	return true;
2237e5c31af7Sopenharmony_ci}
2238e5c31af7Sopenharmony_ci
2239e5c31af7Sopenharmony_cibool DrawTestSpec::AttributeSpec::isBufferStrideAligned (void) const
2240e5c31af7Sopenharmony_ci{
2241e5c31af7Sopenharmony_ci	const bool inputTypePacked = inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10;
2242e5c31af7Sopenharmony_ci
2243e5c31af7Sopenharmony_ci	// Buffer alignment, offset is a multiple of underlying data type size?
2244e5c31af7Sopenharmony_ci	if (storage == STORAGE_BUFFER)
2245e5c31af7Sopenharmony_ci	{
2246e5c31af7Sopenharmony_ci		int dataTypeSize = gls::DrawTestSpec::inputTypeSize(inputType);
2247e5c31af7Sopenharmony_ci		if (inputTypePacked)
2248e5c31af7Sopenharmony_ci			dataTypeSize = 4;
2249e5c31af7Sopenharmony_ci
2250e5c31af7Sopenharmony_ci		if (stride % dataTypeSize != 0)
2251e5c31af7Sopenharmony_ci			return false;
2252e5c31af7Sopenharmony_ci	}
2253e5c31af7Sopenharmony_ci
2254e5c31af7Sopenharmony_ci	return true;
2255e5c31af7Sopenharmony_ci}
2256e5c31af7Sopenharmony_ci
2257e5c31af7Sopenharmony_cistd::string DrawTestSpec::targetToString(Target target)
2258e5c31af7Sopenharmony_ci{
2259e5c31af7Sopenharmony_ci	static const char* targets[] =
2260e5c31af7Sopenharmony_ci	{
2261e5c31af7Sopenharmony_ci		"element_array",	// TARGET_ELEMENT_ARRAY = 0,
2262e5c31af7Sopenharmony_ci		"array"				// TARGET_ARRAY,
2263e5c31af7Sopenharmony_ci	};
2264e5c31af7Sopenharmony_ci
2265e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::TARGET_LAST>(targets, (int)target);
2266e5c31af7Sopenharmony_ci}
2267e5c31af7Sopenharmony_ci
2268e5c31af7Sopenharmony_cistd::string DrawTestSpec::inputTypeToString(InputType type)
2269e5c31af7Sopenharmony_ci{
2270e5c31af7Sopenharmony_ci	static const char* types[] =
2271e5c31af7Sopenharmony_ci	{
2272e5c31af7Sopenharmony_ci		"float",			// INPUTTYPE_FLOAT = 0,
2273e5c31af7Sopenharmony_ci		"fixed",			// INPUTTYPE_FIXED,
2274e5c31af7Sopenharmony_ci		"double",			// INPUTTYPE_DOUBLE
2275e5c31af7Sopenharmony_ci
2276e5c31af7Sopenharmony_ci		"byte",				// INPUTTYPE_BYTE,
2277e5c31af7Sopenharmony_ci		"short",			// INPUTTYPE_SHORT,
2278e5c31af7Sopenharmony_ci
2279e5c31af7Sopenharmony_ci		"unsigned_byte",	// INPUTTYPE_UNSIGNED_BYTE,
2280e5c31af7Sopenharmony_ci		"unsigned_short",	// INPUTTYPE_UNSIGNED_SHORT,
2281e5c31af7Sopenharmony_ci
2282e5c31af7Sopenharmony_ci		"int",						// INPUTTYPE_INT,
2283e5c31af7Sopenharmony_ci		"unsigned_int",				// INPUTTYPE_UNSIGNED_INT,
2284e5c31af7Sopenharmony_ci		"half",						// INPUTTYPE_HALF,
2285e5c31af7Sopenharmony_ci		"unsigned_int2_10_10_10",	// INPUTTYPE_UNSIGNED_INT_2_10_10_10,
2286e5c31af7Sopenharmony_ci		"int2_10_10_10"				// INPUTTYPE_INT_2_10_10_10,
2287e5c31af7Sopenharmony_ci	};
2288e5c31af7Sopenharmony_ci
2289e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::INPUTTYPE_LAST>(types, (int)type);
2290e5c31af7Sopenharmony_ci}
2291e5c31af7Sopenharmony_ci
2292e5c31af7Sopenharmony_cistd::string DrawTestSpec::outputTypeToString(OutputType type)
2293e5c31af7Sopenharmony_ci{
2294e5c31af7Sopenharmony_ci	static const char* types[] =
2295e5c31af7Sopenharmony_ci	{
2296e5c31af7Sopenharmony_ci		"float",		// OUTPUTTYPE_FLOAT = 0,
2297e5c31af7Sopenharmony_ci		"vec2",			// OUTPUTTYPE_VEC2,
2298e5c31af7Sopenharmony_ci		"vec3",			// OUTPUTTYPE_VEC3,
2299e5c31af7Sopenharmony_ci		"vec4",			// OUTPUTTYPE_VEC4,
2300e5c31af7Sopenharmony_ci
2301e5c31af7Sopenharmony_ci		"int",			// OUTPUTTYPE_INT,
2302e5c31af7Sopenharmony_ci		"uint",			// OUTPUTTYPE_UINT,
2303e5c31af7Sopenharmony_ci
2304e5c31af7Sopenharmony_ci		"ivec2",		// OUTPUTTYPE_IVEC2,
2305e5c31af7Sopenharmony_ci		"ivec3",		// OUTPUTTYPE_IVEC3,
2306e5c31af7Sopenharmony_ci		"ivec4",		// OUTPUTTYPE_IVEC4,
2307e5c31af7Sopenharmony_ci
2308e5c31af7Sopenharmony_ci		"uvec2",		// OUTPUTTYPE_UVEC2,
2309e5c31af7Sopenharmony_ci		"uvec3",		// OUTPUTTYPE_UVEC3,
2310e5c31af7Sopenharmony_ci		"uvec4",		// OUTPUTTYPE_UVEC4,
2311e5c31af7Sopenharmony_ci	};
2312e5c31af7Sopenharmony_ci
2313e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::OUTPUTTYPE_LAST>(types, (int)type);
2314e5c31af7Sopenharmony_ci}
2315e5c31af7Sopenharmony_ci
2316e5c31af7Sopenharmony_cistd::string DrawTestSpec::usageTypeToString(Usage usage)
2317e5c31af7Sopenharmony_ci{
2318e5c31af7Sopenharmony_ci	static const char* usages[] =
2319e5c31af7Sopenharmony_ci	{
2320e5c31af7Sopenharmony_ci		"dynamic_draw",	// USAGE_DYNAMIC_DRAW = 0,
2321e5c31af7Sopenharmony_ci		"static_draw",	// USAGE_STATIC_DRAW,
2322e5c31af7Sopenharmony_ci		"stream_draw",	// USAGE_STREAM_DRAW,
2323e5c31af7Sopenharmony_ci
2324e5c31af7Sopenharmony_ci		"stream_read",	// USAGE_STREAM_READ,
2325e5c31af7Sopenharmony_ci		"stream_copy",	// USAGE_STREAM_COPY,
2326e5c31af7Sopenharmony_ci
2327e5c31af7Sopenharmony_ci		"static_read",	// USAGE_STATIC_READ,
2328e5c31af7Sopenharmony_ci		"static_copy",	// USAGE_STATIC_COPY,
2329e5c31af7Sopenharmony_ci
2330e5c31af7Sopenharmony_ci		"dynamic_read",	// USAGE_DYNAMIC_READ,
2331e5c31af7Sopenharmony_ci		"dynamic_copy",	// USAGE_DYNAMIC_COPY,
2332e5c31af7Sopenharmony_ci	};
2333e5c31af7Sopenharmony_ci
2334e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::USAGE_LAST>(usages, (int)usage);
2335e5c31af7Sopenharmony_ci}
2336e5c31af7Sopenharmony_ci
2337e5c31af7Sopenharmony_cistd::string	DrawTestSpec::storageToString (Storage storage)
2338e5c31af7Sopenharmony_ci{
2339e5c31af7Sopenharmony_ci	static const char* storages[] =
2340e5c31af7Sopenharmony_ci	{
2341e5c31af7Sopenharmony_ci		"user_ptr",	// STORAGE_USER = 0,
2342e5c31af7Sopenharmony_ci		"buffer"	// STORAGE_BUFFER,
2343e5c31af7Sopenharmony_ci	};
2344e5c31af7Sopenharmony_ci
2345e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::STORAGE_LAST>(storages, (int)storage);
2346e5c31af7Sopenharmony_ci}
2347e5c31af7Sopenharmony_ci
2348e5c31af7Sopenharmony_cistd::string DrawTestSpec::primitiveToString (Primitive primitive)
2349e5c31af7Sopenharmony_ci{
2350e5c31af7Sopenharmony_ci	static const char* primitives[] =
2351e5c31af7Sopenharmony_ci	{
2352e5c31af7Sopenharmony_ci		"points",					// PRIMITIVE_POINTS ,
2353e5c31af7Sopenharmony_ci		"triangles",				// PRIMITIVE_TRIANGLES,
2354e5c31af7Sopenharmony_ci		"triangle_fan",				// PRIMITIVE_TRIANGLE_FAN,
2355e5c31af7Sopenharmony_ci		"triangle_strip",			// PRIMITIVE_TRIANGLE_STRIP,
2356e5c31af7Sopenharmony_ci		"lines",					// PRIMITIVE_LINES
2357e5c31af7Sopenharmony_ci		"line_strip",				// PRIMITIVE_LINE_STRIP
2358e5c31af7Sopenharmony_ci		"line_loop",				// PRIMITIVE_LINE_LOOP
2359e5c31af7Sopenharmony_ci		"lines_adjacency",			// PRIMITIVE_LINES_ADJACENCY
2360e5c31af7Sopenharmony_ci		"line_strip_adjacency",		// PRIMITIVE_LINE_STRIP_ADJACENCY
2361e5c31af7Sopenharmony_ci		"triangles_adjacency",		// PRIMITIVE_TRIANGLES_ADJACENCY
2362e5c31af7Sopenharmony_ci		"triangle_strip_adjacency",	// PRIMITIVE_TRIANGLE_STRIP_ADJACENCY
2363e5c31af7Sopenharmony_ci	};
2364e5c31af7Sopenharmony_ci
2365e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::PRIMITIVE_LAST>(primitives, (int)primitive);
2366e5c31af7Sopenharmony_ci}
2367e5c31af7Sopenharmony_ci
2368e5c31af7Sopenharmony_cistd::string DrawTestSpec::indexTypeToString (IndexType type)
2369e5c31af7Sopenharmony_ci{
2370e5c31af7Sopenharmony_ci	static const char* indexTypes[] =
2371e5c31af7Sopenharmony_ci	{
2372e5c31af7Sopenharmony_ci		"byte",		// INDEXTYPE_BYTE = 0,
2373e5c31af7Sopenharmony_ci		"short",	// INDEXTYPE_SHORT,
2374e5c31af7Sopenharmony_ci		"int",		// INDEXTYPE_INT,
2375e5c31af7Sopenharmony_ci	};
2376e5c31af7Sopenharmony_ci
2377e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::INDEXTYPE_LAST>(indexTypes, (int)type);
2378e5c31af7Sopenharmony_ci}
2379e5c31af7Sopenharmony_ci
2380e5c31af7Sopenharmony_cistd::string DrawTestSpec::drawMethodToString (DrawTestSpec::DrawMethod method)
2381e5c31af7Sopenharmony_ci{
2382e5c31af7Sopenharmony_ci	static const char* methods[] =
2383e5c31af7Sopenharmony_ci	{
2384e5c31af7Sopenharmony_ci		"draw_arrays",							//!< DRAWMETHOD_DRAWARRAYS
2385e5c31af7Sopenharmony_ci		"draw_arrays_instanced",				//!< DRAWMETHOD_DRAWARRAYS_INSTANCED
2386e5c31af7Sopenharmony_ci		"draw_arrays_indirect",					//!< DRAWMETHOD_DRAWARRAYS_INDIRECT
2387e5c31af7Sopenharmony_ci		"draw_elements",						//!< DRAWMETHOD_DRAWELEMENTS
2388e5c31af7Sopenharmony_ci		"draw_range_elements",					//!< DRAWMETHOD_DRAWELEMENTS_RANGED
2389e5c31af7Sopenharmony_ci		"draw_elements_instanced",				//!< DRAWMETHOD_DRAWELEMENTS_INSTANCED
2390e5c31af7Sopenharmony_ci		"draw_elements_indirect",				//!< DRAWMETHOD_DRAWELEMENTS_INDIRECT
2391e5c31af7Sopenharmony_ci		"draw_elements_base_vertex",			//!< DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
2392e5c31af7Sopenharmony_ci		"draw_elements_instanced_base_vertex",	//!< DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
2393e5c31af7Sopenharmony_ci		"draw_range_elements_base_vertex",		//!< DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
2394e5c31af7Sopenharmony_ci	};
2395e5c31af7Sopenharmony_ci
2396e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::DRAWMETHOD_LAST>(methods, (int)method);
2397e5c31af7Sopenharmony_ci}
2398e5c31af7Sopenharmony_ci
2399e5c31af7Sopenharmony_ciint DrawTestSpec::inputTypeSize (InputType type)
2400e5c31af7Sopenharmony_ci{
2401e5c31af7Sopenharmony_ci	static const int size[] =
2402e5c31af7Sopenharmony_ci	{
2403e5c31af7Sopenharmony_ci		(int)sizeof(float),			// INPUTTYPE_FLOAT = 0,
2404e5c31af7Sopenharmony_ci		(int)sizeof(deInt32),		// INPUTTYPE_FIXED,
2405e5c31af7Sopenharmony_ci		(int)sizeof(double),		// INPUTTYPE_DOUBLE
2406e5c31af7Sopenharmony_ci
2407e5c31af7Sopenharmony_ci		(int)sizeof(deInt8),		// INPUTTYPE_BYTE,
2408e5c31af7Sopenharmony_ci		(int)sizeof(deInt16),		// INPUTTYPE_SHORT,
2409e5c31af7Sopenharmony_ci
2410e5c31af7Sopenharmony_ci		(int)sizeof(deUint8),		// INPUTTYPE_UNSIGNED_BYTE,
2411e5c31af7Sopenharmony_ci		(int)sizeof(deUint16),		// INPUTTYPE_UNSIGNED_SHORT,
2412e5c31af7Sopenharmony_ci
2413e5c31af7Sopenharmony_ci		(int)sizeof(deInt32),		// INPUTTYPE_INT,
2414e5c31af7Sopenharmony_ci		(int)sizeof(deUint32),		// INPUTTYPE_UNSIGNED_INT,
2415e5c31af7Sopenharmony_ci		(int)sizeof(deFloat16),		// INPUTTYPE_HALF,
2416e5c31af7Sopenharmony_ci		(int)sizeof(deUint32) / 4,	// INPUTTYPE_UNSIGNED_INT_2_10_10_10,
2417e5c31af7Sopenharmony_ci		(int)sizeof(deUint32) / 4	// INPUTTYPE_INT_2_10_10_10,
2418e5c31af7Sopenharmony_ci	};
2419e5c31af7Sopenharmony_ci
2420e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::INPUTTYPE_LAST>(size, (int)type);
2421e5c31af7Sopenharmony_ci}
2422e5c31af7Sopenharmony_ci
2423e5c31af7Sopenharmony_ciint DrawTestSpec::indexTypeSize (IndexType type)
2424e5c31af7Sopenharmony_ci{
2425e5c31af7Sopenharmony_ci	static const int size[] =
2426e5c31af7Sopenharmony_ci	{
2427e5c31af7Sopenharmony_ci		sizeof(deUint8),	// INDEXTYPE_BYTE,
2428e5c31af7Sopenharmony_ci		sizeof(deUint16),	// INDEXTYPE_SHORT,
2429e5c31af7Sopenharmony_ci		sizeof(deUint32),	// INDEXTYPE_INT,
2430e5c31af7Sopenharmony_ci	};
2431e5c31af7Sopenharmony_ci
2432e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<DrawTestSpec::INDEXTYPE_LAST>(size, (int)type);
2433e5c31af7Sopenharmony_ci}
2434e5c31af7Sopenharmony_ci
2435e5c31af7Sopenharmony_cistd::string DrawTestSpec::getName (void) const
2436e5c31af7Sopenharmony_ci{
2437e5c31af7Sopenharmony_ci	const MethodInfo	methodInfo	= getMethodInfo(drawMethod);
2438e5c31af7Sopenharmony_ci	const bool			hasFirst	= methodInfo.first;
2439e5c31af7Sopenharmony_ci	const bool			instanced	= methodInfo.instanced;
2440e5c31af7Sopenharmony_ci	const bool			ranged		= methodInfo.ranged;
2441e5c31af7Sopenharmony_ci	const bool			indexed		= methodInfo.indexed;
2442e5c31af7Sopenharmony_ci
2443e5c31af7Sopenharmony_ci	std::stringstream name;
2444e5c31af7Sopenharmony_ci
2445e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < attribs.size(); ++ndx)
2446e5c31af7Sopenharmony_ci	{
2447e5c31af7Sopenharmony_ci		const AttributeSpec& attrib = attribs[ndx];
2448e5c31af7Sopenharmony_ci
2449e5c31af7Sopenharmony_ci		if (attribs.size() > 1)
2450e5c31af7Sopenharmony_ci			name << "attrib" << ndx << "_";
2451e5c31af7Sopenharmony_ci
2452e5c31af7Sopenharmony_ci		if (ndx == 0|| attrib.additionalPositionAttribute)
2453e5c31af7Sopenharmony_ci			name << "pos_";
2454e5c31af7Sopenharmony_ci		else
2455e5c31af7Sopenharmony_ci			name << "col_";
2456e5c31af7Sopenharmony_ci
2457e5c31af7Sopenharmony_ci		if (attrib.useDefaultAttribute)
2458e5c31af7Sopenharmony_ci		{
2459e5c31af7Sopenharmony_ci			name
2460e5c31af7Sopenharmony_ci				<< "non_array_"
2461e5c31af7Sopenharmony_ci				<< DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << "_"
2462e5c31af7Sopenharmony_ci				<< attrib.componentCount << "_"
2463e5c31af7Sopenharmony_ci				<< DrawTestSpec::outputTypeToString(attrib.outputType) << "_";
2464e5c31af7Sopenharmony_ci		}
2465e5c31af7Sopenharmony_ci		else
2466e5c31af7Sopenharmony_ci		{
2467e5c31af7Sopenharmony_ci			name
2468e5c31af7Sopenharmony_ci				<< DrawTestSpec::storageToString(attrib.storage) << "_"
2469e5c31af7Sopenharmony_ci				<< attrib.offset << "_"
2470e5c31af7Sopenharmony_ci				<< attrib.stride << "_"
2471e5c31af7Sopenharmony_ci				<< DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType);
2472e5c31af7Sopenharmony_ci			if (attrib.inputType != DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10 && attrib.inputType != DrawTestSpec::INPUTTYPE_INT_2_10_10_10)
2473e5c31af7Sopenharmony_ci				name << attrib.componentCount;
2474e5c31af7Sopenharmony_ci			name
2475e5c31af7Sopenharmony_ci				<< "_"
2476e5c31af7Sopenharmony_ci				<< (attrib.normalize ? "normalized_" : "")
2477e5c31af7Sopenharmony_ci				<< DrawTestSpec::outputTypeToString(attrib.outputType) << "_"
2478e5c31af7Sopenharmony_ci				<< DrawTestSpec::usageTypeToString(attrib.usage) << "_"
2479e5c31af7Sopenharmony_ci				<< attrib.instanceDivisor << "_";
2480e5c31af7Sopenharmony_ci		}
2481e5c31af7Sopenharmony_ci	}
2482e5c31af7Sopenharmony_ci
2483e5c31af7Sopenharmony_ci	if (indexed)
2484e5c31af7Sopenharmony_ci		name
2485e5c31af7Sopenharmony_ci			<< "index_" << DrawTestSpec::indexTypeToString(indexType) << "_"
2486e5c31af7Sopenharmony_ci			<< DrawTestSpec::storageToString(indexStorage) << "_"
2487e5c31af7Sopenharmony_ci			<< "offset" << indexPointerOffset << "_";
2488e5c31af7Sopenharmony_ci	if (hasFirst)
2489e5c31af7Sopenharmony_ci		name << "first" << first << "_";
2490e5c31af7Sopenharmony_ci	if (ranged)
2491e5c31af7Sopenharmony_ci		name << "ranged_" << indexMin << "_" << indexMax << "_";
2492e5c31af7Sopenharmony_ci	if (instanced)
2493e5c31af7Sopenharmony_ci		name << "instances" << instanceCount << "_";
2494e5c31af7Sopenharmony_ci
2495e5c31af7Sopenharmony_ci	switch (primitive)
2496e5c31af7Sopenharmony_ci	{
2497e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_POINTS:
2498e5c31af7Sopenharmony_ci			name << "points_";
2499e5c31af7Sopenharmony_ci			break;
2500e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES:
2501e5c31af7Sopenharmony_ci			name << "triangles_";
2502e5c31af7Sopenharmony_ci			break;
2503e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
2504e5c31af7Sopenharmony_ci			name << "triangle_fan_";
2505e5c31af7Sopenharmony_ci			break;
2506e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
2507e5c31af7Sopenharmony_ci			name << "triangle_strip_";
2508e5c31af7Sopenharmony_ci			break;
2509e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES:
2510e5c31af7Sopenharmony_ci			name << "lines_";
2511e5c31af7Sopenharmony_ci			break;
2512e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP:
2513e5c31af7Sopenharmony_ci			name << "line_strip_";
2514e5c31af7Sopenharmony_ci			break;
2515e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_LOOP:
2516e5c31af7Sopenharmony_ci			name << "line_loop_";
2517e5c31af7Sopenharmony_ci			break;
2518e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
2519e5c31af7Sopenharmony_ci			name << "line_adjancency";
2520e5c31af7Sopenharmony_ci			break;
2521e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
2522e5c31af7Sopenharmony_ci			name << "line_strip_adjancency";
2523e5c31af7Sopenharmony_ci			break;
2524e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
2525e5c31af7Sopenharmony_ci			name << "triangles_adjancency";
2526e5c31af7Sopenharmony_ci			break;
2527e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
2528e5c31af7Sopenharmony_ci			name << "triangle_strip_adjancency";
2529e5c31af7Sopenharmony_ci			break;
2530e5c31af7Sopenharmony_ci		default:
2531e5c31af7Sopenharmony_ci			DE_ASSERT(false);
2532e5c31af7Sopenharmony_ci			break;
2533e5c31af7Sopenharmony_ci	}
2534e5c31af7Sopenharmony_ci
2535e5c31af7Sopenharmony_ci	name << primitiveCount;
2536e5c31af7Sopenharmony_ci
2537e5c31af7Sopenharmony_ci	return name.str();
2538e5c31af7Sopenharmony_ci}
2539e5c31af7Sopenharmony_ci
2540e5c31af7Sopenharmony_cistd::string DrawTestSpec::getDesc (void) const
2541e5c31af7Sopenharmony_ci{
2542e5c31af7Sopenharmony_ci	std::stringstream desc;
2543e5c31af7Sopenharmony_ci
2544e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < attribs.size(); ++ndx)
2545e5c31af7Sopenharmony_ci	{
2546e5c31af7Sopenharmony_ci		const AttributeSpec& attrib = attribs[ndx];
2547e5c31af7Sopenharmony_ci
2548e5c31af7Sopenharmony_ci		if (attrib.useDefaultAttribute)
2549e5c31af7Sopenharmony_ci		{
2550e5c31af7Sopenharmony_ci			desc
2551e5c31af7Sopenharmony_ci				<< "Attribute " << ndx << ": default, " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position ,") : ("color ,"))
2552e5c31af7Sopenharmony_ci				<< "input datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << ", "
2553e5c31af7Sopenharmony_ci				<< "input component count " << attrib.componentCount << ", "
2554e5c31af7Sopenharmony_ci				<< "used as " << DrawTestSpec::outputTypeToString(attrib.outputType) << ", ";
2555e5c31af7Sopenharmony_ci		}
2556e5c31af7Sopenharmony_ci		else
2557e5c31af7Sopenharmony_ci		{
2558e5c31af7Sopenharmony_ci			desc
2559e5c31af7Sopenharmony_ci				<< "Attribute " << ndx << ": " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position ,") : ("color ,"))
2560e5c31af7Sopenharmony_ci				<< "Storage in " << DrawTestSpec::storageToString(attrib.storage) << ", "
2561e5c31af7Sopenharmony_ci				<< "stride " << attrib.stride << ", "
2562e5c31af7Sopenharmony_ci				<< "input datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << ", "
2563e5c31af7Sopenharmony_ci				<< "input component count " << attrib.componentCount << ", "
2564e5c31af7Sopenharmony_ci				<< (attrib.normalize ? "normalized, " : "")
2565e5c31af7Sopenharmony_ci				<< "used as " << DrawTestSpec::outputTypeToString(attrib.outputType) << ", "
2566e5c31af7Sopenharmony_ci				<< "instance divisor " << attrib.instanceDivisor << ", ";
2567e5c31af7Sopenharmony_ci		}
2568e5c31af7Sopenharmony_ci	}
2569e5c31af7Sopenharmony_ci
2570e5c31af7Sopenharmony_ci	if (drawMethod == DRAWMETHOD_DRAWARRAYS)
2571e5c31af7Sopenharmony_ci	{
2572e5c31af7Sopenharmony_ci		desc
2573e5c31af7Sopenharmony_ci			<< "drawArrays(), "
2574e5c31af7Sopenharmony_ci			<< "first " << first << ", ";
2575e5c31af7Sopenharmony_ci	}
2576e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INSTANCED)
2577e5c31af7Sopenharmony_ci	{
2578e5c31af7Sopenharmony_ci		desc
2579e5c31af7Sopenharmony_ci			<< "drawArraysInstanced(), "
2580e5c31af7Sopenharmony_ci			<< "first " << first << ", "
2581e5c31af7Sopenharmony_ci			<< "instance count " << instanceCount << ", ";
2582e5c31af7Sopenharmony_ci	}
2583e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS)
2584e5c31af7Sopenharmony_ci	{
2585e5c31af7Sopenharmony_ci		desc
2586e5c31af7Sopenharmony_ci			<< "drawElements(), "
2587e5c31af7Sopenharmony_ci			<< "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2588e5c31af7Sopenharmony_ci			<< "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2589e5c31af7Sopenharmony_ci			<< "index offset " << indexPointerOffset << ", ";
2590e5c31af7Sopenharmony_ci	}
2591e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_RANGED)
2592e5c31af7Sopenharmony_ci	{
2593e5c31af7Sopenharmony_ci		desc
2594e5c31af7Sopenharmony_ci			<< "drawElementsRanged(), "
2595e5c31af7Sopenharmony_ci			<< "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2596e5c31af7Sopenharmony_ci			<< "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2597e5c31af7Sopenharmony_ci			<< "index offset " << indexPointerOffset << ", "
2598e5c31af7Sopenharmony_ci			<< "range start " << indexMin << ", "
2599e5c31af7Sopenharmony_ci			<< "range end " << indexMax << ", ";
2600e5c31af7Sopenharmony_ci	}
2601e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INSTANCED)
2602e5c31af7Sopenharmony_ci	{
2603e5c31af7Sopenharmony_ci		desc
2604e5c31af7Sopenharmony_ci			<< "drawElementsInstanced(), "
2605e5c31af7Sopenharmony_ci			<< "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2606e5c31af7Sopenharmony_ci			<< "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2607e5c31af7Sopenharmony_ci			<< "index offset " << indexPointerOffset << ", "
2608e5c31af7Sopenharmony_ci			<< "instance count " << instanceCount << ", ";
2609e5c31af7Sopenharmony_ci	}
2610e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INDIRECT)
2611e5c31af7Sopenharmony_ci	{
2612e5c31af7Sopenharmony_ci		desc
2613e5c31af7Sopenharmony_ci			<< "drawArraysIndirect(), "
2614e5c31af7Sopenharmony_ci			<< "first " << first << ", "
2615e5c31af7Sopenharmony_ci			<< "instance count " << instanceCount << ", "
2616e5c31af7Sopenharmony_ci			<< "indirect offset " << indirectOffset << ", ";
2617e5c31af7Sopenharmony_ci	}
2618e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INDIRECT)
2619e5c31af7Sopenharmony_ci	{
2620e5c31af7Sopenharmony_ci		desc
2621e5c31af7Sopenharmony_ci			<< "drawElementsIndirect(), "
2622e5c31af7Sopenharmony_ci			<< "index type " << DrawTestSpec::indexTypeToString(indexType) << ", "
2623e5c31af7Sopenharmony_ci			<< "index storage in " << DrawTestSpec::storageToString(indexStorage) << ", "
2624e5c31af7Sopenharmony_ci			<< "index offset " << indexPointerOffset << ", "
2625e5c31af7Sopenharmony_ci			<< "instance count " << instanceCount << ", "
2626e5c31af7Sopenharmony_ci			<< "indirect offset " << indirectOffset << ", "
2627e5c31af7Sopenharmony_ci			<< "base vertex " << baseVertex << ", ";
2628e5c31af7Sopenharmony_ci	}
2629e5c31af7Sopenharmony_ci	else
2630e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
2631e5c31af7Sopenharmony_ci
2632e5c31af7Sopenharmony_ci	desc << primitiveCount;
2633e5c31af7Sopenharmony_ci
2634e5c31af7Sopenharmony_ci	switch (primitive)
2635e5c31af7Sopenharmony_ci	{
2636e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_POINTS:
2637e5c31af7Sopenharmony_ci			desc << "points";
2638e5c31af7Sopenharmony_ci			break;
2639e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES:
2640e5c31af7Sopenharmony_ci			desc << "triangles";
2641e5c31af7Sopenharmony_ci			break;
2642e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
2643e5c31af7Sopenharmony_ci			desc << "triangles (fan)";
2644e5c31af7Sopenharmony_ci			break;
2645e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
2646e5c31af7Sopenharmony_ci			desc << "triangles (strip)";
2647e5c31af7Sopenharmony_ci			break;
2648e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES:
2649e5c31af7Sopenharmony_ci			desc << "lines";
2650e5c31af7Sopenharmony_ci			break;
2651e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP:
2652e5c31af7Sopenharmony_ci			desc << "lines (strip)";
2653e5c31af7Sopenharmony_ci			break;
2654e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_LOOP:
2655e5c31af7Sopenharmony_ci			desc << "lines (loop)";
2656e5c31af7Sopenharmony_ci			break;
2657e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
2658e5c31af7Sopenharmony_ci			desc << "lines (adjancency)";
2659e5c31af7Sopenharmony_ci			break;
2660e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
2661e5c31af7Sopenharmony_ci			desc << "lines (strip, adjancency)";
2662e5c31af7Sopenharmony_ci			break;
2663e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
2664e5c31af7Sopenharmony_ci			desc << "triangles (adjancency)";
2665e5c31af7Sopenharmony_ci			break;
2666e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
2667e5c31af7Sopenharmony_ci			desc << "triangles (strip, adjancency)";
2668e5c31af7Sopenharmony_ci			break;
2669e5c31af7Sopenharmony_ci		default:
2670e5c31af7Sopenharmony_ci			DE_ASSERT(false);
2671e5c31af7Sopenharmony_ci			break;
2672e5c31af7Sopenharmony_ci	}
2673e5c31af7Sopenharmony_ci
2674e5c31af7Sopenharmony_ci	return desc.str();
2675e5c31af7Sopenharmony_ci}
2676e5c31af7Sopenharmony_ci
2677e5c31af7Sopenharmony_cistd::string DrawTestSpec::getMultilineDesc (void) const
2678e5c31af7Sopenharmony_ci{
2679e5c31af7Sopenharmony_ci	std::stringstream desc;
2680e5c31af7Sopenharmony_ci
2681e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < attribs.size(); ++ndx)
2682e5c31af7Sopenharmony_ci	{
2683e5c31af7Sopenharmony_ci		const AttributeSpec& attrib = attribs[ndx];
2684e5c31af7Sopenharmony_ci
2685e5c31af7Sopenharmony_ci		if (attrib.useDefaultAttribute)
2686e5c31af7Sopenharmony_ci		{
2687e5c31af7Sopenharmony_ci			desc
2688e5c31af7Sopenharmony_ci				<< "Attribute " << ndx << ": default, " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position\n") : ("color\n"))
2689e5c31af7Sopenharmony_ci				<< "\tinput datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << "\n"
2690e5c31af7Sopenharmony_ci				<< "\tinput component count " << attrib.componentCount << "\n"
2691e5c31af7Sopenharmony_ci				<< "\tused as " << DrawTestSpec::outputTypeToString(attrib.outputType) << "\n";
2692e5c31af7Sopenharmony_ci		}
2693e5c31af7Sopenharmony_ci		else
2694e5c31af7Sopenharmony_ci		{
2695e5c31af7Sopenharmony_ci			desc
2696e5c31af7Sopenharmony_ci				<< "Attribute " << ndx << ": " << ((ndx == 0|| attrib.additionalPositionAttribute) ? ("position\n") : ("color\n"))
2697e5c31af7Sopenharmony_ci				<< "\tStorage in " << DrawTestSpec::storageToString(attrib.storage) << "\n"
2698e5c31af7Sopenharmony_ci				<< "\tstride " << attrib.stride << "\n"
2699e5c31af7Sopenharmony_ci				<< "\tinput datatype " << DrawTestSpec::inputTypeToString((DrawTestSpec::InputType)attrib.inputType) << "\n"
2700e5c31af7Sopenharmony_ci				<< "\tinput component count " << attrib.componentCount << "\n"
2701e5c31af7Sopenharmony_ci				<< (attrib.normalize ? "\tnormalized\n" : "")
2702e5c31af7Sopenharmony_ci				<< "\tused as " << DrawTestSpec::outputTypeToString(attrib.outputType) << "\n"
2703e5c31af7Sopenharmony_ci				<< "\tinstance divisor " << attrib.instanceDivisor << "\n";
2704e5c31af7Sopenharmony_ci		}
2705e5c31af7Sopenharmony_ci	}
2706e5c31af7Sopenharmony_ci
2707e5c31af7Sopenharmony_ci	if (drawMethod == DRAWMETHOD_DRAWARRAYS)
2708e5c31af7Sopenharmony_ci	{
2709e5c31af7Sopenharmony_ci		desc
2710e5c31af7Sopenharmony_ci			<< "drawArrays()\n"
2711e5c31af7Sopenharmony_ci			<< "\tfirst " << first << "\n";
2712e5c31af7Sopenharmony_ci	}
2713e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INSTANCED)
2714e5c31af7Sopenharmony_ci	{
2715e5c31af7Sopenharmony_ci		desc
2716e5c31af7Sopenharmony_ci			<< "drawArraysInstanced()\n"
2717e5c31af7Sopenharmony_ci			<< "\tfirst " << first << "\n"
2718e5c31af7Sopenharmony_ci			<< "\tinstance count " << instanceCount << "\n";
2719e5c31af7Sopenharmony_ci	}
2720e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS)
2721e5c31af7Sopenharmony_ci	{
2722e5c31af7Sopenharmony_ci		desc
2723e5c31af7Sopenharmony_ci			<< "drawElements()\n"
2724e5c31af7Sopenharmony_ci			<< "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2725e5c31af7Sopenharmony_ci			<< "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2726e5c31af7Sopenharmony_ci			<< "\tindex offset " << indexPointerOffset << "\n";
2727e5c31af7Sopenharmony_ci	}
2728e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_RANGED)
2729e5c31af7Sopenharmony_ci	{
2730e5c31af7Sopenharmony_ci		desc
2731e5c31af7Sopenharmony_ci			<< "drawElementsRanged()\n"
2732e5c31af7Sopenharmony_ci			<< "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2733e5c31af7Sopenharmony_ci			<< "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2734e5c31af7Sopenharmony_ci			<< "\tindex offset " << indexPointerOffset << "\n"
2735e5c31af7Sopenharmony_ci			<< "\trange start " << indexMin << "\n"
2736e5c31af7Sopenharmony_ci			<< "\trange end " << indexMax << "\n";
2737e5c31af7Sopenharmony_ci	}
2738e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INSTANCED)
2739e5c31af7Sopenharmony_ci	{
2740e5c31af7Sopenharmony_ci		desc
2741e5c31af7Sopenharmony_ci			<< "drawElementsInstanced()\n"
2742e5c31af7Sopenharmony_ci			<< "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2743e5c31af7Sopenharmony_ci			<< "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2744e5c31af7Sopenharmony_ci			<< "\tindex offset " << indexPointerOffset << "\n"
2745e5c31af7Sopenharmony_ci			<< "\tinstance count " << instanceCount << "\n";
2746e5c31af7Sopenharmony_ci	}
2747e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWARRAYS_INDIRECT)
2748e5c31af7Sopenharmony_ci	{
2749e5c31af7Sopenharmony_ci		desc
2750e5c31af7Sopenharmony_ci			<< "drawArraysIndirect()\n"
2751e5c31af7Sopenharmony_ci			<< "\tfirst " << first << "\n"
2752e5c31af7Sopenharmony_ci			<< "\tinstance count " << instanceCount << "\n"
2753e5c31af7Sopenharmony_ci			<< "\tindirect offset " << indirectOffset << "\n";
2754e5c31af7Sopenharmony_ci	}
2755e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INDIRECT)
2756e5c31af7Sopenharmony_ci	{
2757e5c31af7Sopenharmony_ci		desc
2758e5c31af7Sopenharmony_ci			<< "drawElementsIndirect()\n"
2759e5c31af7Sopenharmony_ci			<< "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2760e5c31af7Sopenharmony_ci			<< "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2761e5c31af7Sopenharmony_ci			<< "\tindex offset " << indexPointerOffset << "\n"
2762e5c31af7Sopenharmony_ci			<< "\tinstance count " << instanceCount << "\n"
2763e5c31af7Sopenharmony_ci			<< "\tindirect offset " << indirectOffset << "\n"
2764e5c31af7Sopenharmony_ci			<< "\tbase vertex " << baseVertex << "\n";
2765e5c31af7Sopenharmony_ci	}
2766e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
2767e5c31af7Sopenharmony_ci	{
2768e5c31af7Sopenharmony_ci		desc
2769e5c31af7Sopenharmony_ci			<< "drawElementsBaseVertex()\n"
2770e5c31af7Sopenharmony_ci			<< "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2771e5c31af7Sopenharmony_ci			<< "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2772e5c31af7Sopenharmony_ci			<< "\tindex offset " << indexPointerOffset << "\n"
2773e5c31af7Sopenharmony_ci			<< "\tbase vertex " << baseVertex << "\n";
2774e5c31af7Sopenharmony_ci	}
2775e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX)
2776e5c31af7Sopenharmony_ci	{
2777e5c31af7Sopenharmony_ci		desc
2778e5c31af7Sopenharmony_ci			<< "drawElementsInstancedBaseVertex()\n"
2779e5c31af7Sopenharmony_ci			<< "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2780e5c31af7Sopenharmony_ci			<< "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2781e5c31af7Sopenharmony_ci			<< "\tindex offset " << indexPointerOffset << "\n"
2782e5c31af7Sopenharmony_ci			<< "\tinstance count " << instanceCount << "\n"
2783e5c31af7Sopenharmony_ci			<< "\tbase vertex " << baseVertex << "\n";
2784e5c31af7Sopenharmony_ci	}
2785e5c31af7Sopenharmony_ci	else if (drawMethod == DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
2786e5c31af7Sopenharmony_ci	{
2787e5c31af7Sopenharmony_ci		desc
2788e5c31af7Sopenharmony_ci			<< "drawRangeElementsBaseVertex()\n"
2789e5c31af7Sopenharmony_ci			<< "\tindex type " << DrawTestSpec::indexTypeToString(indexType) << "\n"
2790e5c31af7Sopenharmony_ci			<< "\tindex storage in " << DrawTestSpec::storageToString(indexStorage) << "\n"
2791e5c31af7Sopenharmony_ci			<< "\tindex offset " << indexPointerOffset << "\n"
2792e5c31af7Sopenharmony_ci			<< "\tbase vertex " << baseVertex << "\n"
2793e5c31af7Sopenharmony_ci			<< "\trange start " << indexMin << "\n"
2794e5c31af7Sopenharmony_ci			<< "\trange end " << indexMax << "\n";
2795e5c31af7Sopenharmony_ci	}
2796e5c31af7Sopenharmony_ci	else
2797e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
2798e5c31af7Sopenharmony_ci
2799e5c31af7Sopenharmony_ci	desc << "\t" << primitiveCount << " ";
2800e5c31af7Sopenharmony_ci
2801e5c31af7Sopenharmony_ci	switch (primitive)
2802e5c31af7Sopenharmony_ci	{
2803e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_POINTS:
2804e5c31af7Sopenharmony_ci			desc << "points";
2805e5c31af7Sopenharmony_ci			break;
2806e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES:
2807e5c31af7Sopenharmony_ci			desc << "triangles";
2808e5c31af7Sopenharmony_ci			break;
2809e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
2810e5c31af7Sopenharmony_ci			desc << "triangles (fan)";
2811e5c31af7Sopenharmony_ci			break;
2812e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
2813e5c31af7Sopenharmony_ci			desc << "triangles (strip)";
2814e5c31af7Sopenharmony_ci			break;
2815e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES:
2816e5c31af7Sopenharmony_ci			desc << "lines";
2817e5c31af7Sopenharmony_ci			break;
2818e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP:
2819e5c31af7Sopenharmony_ci			desc << "lines (strip)";
2820e5c31af7Sopenharmony_ci			break;
2821e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_LOOP:
2822e5c31af7Sopenharmony_ci			desc << "lines (loop)";
2823e5c31af7Sopenharmony_ci			break;
2824e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
2825e5c31af7Sopenharmony_ci			desc << "lines (adjancency)";
2826e5c31af7Sopenharmony_ci			break;
2827e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
2828e5c31af7Sopenharmony_ci			desc << "lines (strip, adjancency)";
2829e5c31af7Sopenharmony_ci			break;
2830e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
2831e5c31af7Sopenharmony_ci			desc << "triangles (adjancency)";
2832e5c31af7Sopenharmony_ci			break;
2833e5c31af7Sopenharmony_ci		case DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
2834e5c31af7Sopenharmony_ci			desc << "triangles (strip, adjancency)";
2835e5c31af7Sopenharmony_ci			break;
2836e5c31af7Sopenharmony_ci		default:
2837e5c31af7Sopenharmony_ci			DE_ASSERT(false);
2838e5c31af7Sopenharmony_ci			break;
2839e5c31af7Sopenharmony_ci	}
2840e5c31af7Sopenharmony_ci
2841e5c31af7Sopenharmony_ci	desc << "\n";
2842e5c31af7Sopenharmony_ci
2843e5c31af7Sopenharmony_ci	return desc.str();
2844e5c31af7Sopenharmony_ci}
2845e5c31af7Sopenharmony_ci
2846e5c31af7Sopenharmony_ciDrawTestSpec::DrawTestSpec (void)
2847e5c31af7Sopenharmony_ci{
2848e5c31af7Sopenharmony_ci	primitive			= PRIMITIVE_LAST;
2849e5c31af7Sopenharmony_ci	primitiveCount		= 0;
2850e5c31af7Sopenharmony_ci	drawMethod			= DRAWMETHOD_LAST;
2851e5c31af7Sopenharmony_ci	indexType			= INDEXTYPE_LAST;
2852e5c31af7Sopenharmony_ci	indexPointerOffset	= 0;
2853e5c31af7Sopenharmony_ci	indexStorage		= STORAGE_LAST;
2854e5c31af7Sopenharmony_ci	first				= 0;
2855e5c31af7Sopenharmony_ci	indexMin			= 0;
2856e5c31af7Sopenharmony_ci	indexMax			= 0;
2857e5c31af7Sopenharmony_ci	instanceCount		= 0;
2858e5c31af7Sopenharmony_ci	indirectOffset		= 0;
2859e5c31af7Sopenharmony_ci	baseVertex			= 0;
2860e5c31af7Sopenharmony_ci}
2861e5c31af7Sopenharmony_ci
2862e5c31af7Sopenharmony_ciint DrawTestSpec::hash (void) const
2863e5c31af7Sopenharmony_ci{
2864e5c31af7Sopenharmony_ci	// Use only drawmode-relevant values in "hashing" as the unrelevant values might not be set (causing non-deterministic behavior).
2865e5c31af7Sopenharmony_ci	const MethodInfo	methodInfo		= getMethodInfo(drawMethod);
2866e5c31af7Sopenharmony_ci	const bool			arrayed			= methodInfo.first;
2867e5c31af7Sopenharmony_ci	const bool			instanced		= methodInfo.instanced;
2868e5c31af7Sopenharmony_ci	const bool			ranged			= methodInfo.ranged;
2869e5c31af7Sopenharmony_ci	const bool			indexed			= methodInfo.indexed;
2870e5c31af7Sopenharmony_ci	const bool			indirect		= methodInfo.indirect;
2871e5c31af7Sopenharmony_ci	const bool			hasBaseVtx		= methodInfo.baseVertex;
2872e5c31af7Sopenharmony_ci
2873e5c31af7Sopenharmony_ci	const int			indexHash		= (!indexed)	? (0) : (int(indexType) + 10 * indexPointerOffset + 100 * int(indexStorage));
2874e5c31af7Sopenharmony_ci	const int			arrayHash		= (!arrayed)	? (0) : (first);
2875e5c31af7Sopenharmony_ci	const int			indexRangeHash	= (!ranged)		? (0) : (indexMin + 10 * indexMax);
2876e5c31af7Sopenharmony_ci	const int			instanceHash	= (!instanced)	? (0) : (instanceCount);
2877e5c31af7Sopenharmony_ci	const int			indirectHash	= (!indirect)	? (0) : (indirectOffset);
2878e5c31af7Sopenharmony_ci	const int			baseVtxHash		= (!hasBaseVtx)	? (0) : (baseVertex);
2879e5c31af7Sopenharmony_ci	const int			basicHash		= int(primitive) + 10 * primitiveCount + 100 * int(drawMethod);
2880e5c31af7Sopenharmony_ci
2881e5c31af7Sopenharmony_ci	return indexHash + 3 * arrayHash + 5 * indexRangeHash + 7 * instanceHash + 13 * basicHash + 17 * (int)attribs.size() + 19 * primitiveCount + 23 * indirectHash + 27 * baseVtxHash;
2882e5c31af7Sopenharmony_ci}
2883e5c31af7Sopenharmony_ci
2884e5c31af7Sopenharmony_cibool DrawTestSpec::valid (void) const
2885e5c31af7Sopenharmony_ci{
2886e5c31af7Sopenharmony_ci	DE_ASSERT(apiType.getProfile() != glu::PROFILE_LAST);
2887e5c31af7Sopenharmony_ci	DE_ASSERT(primitive != PRIMITIVE_LAST);
2888e5c31af7Sopenharmony_ci	DE_ASSERT(drawMethod != DRAWMETHOD_LAST);
2889e5c31af7Sopenharmony_ci
2890e5c31af7Sopenharmony_ci	const MethodInfo methodInfo = getMethodInfo(drawMethod);
2891e5c31af7Sopenharmony_ci
2892e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2893e5c31af7Sopenharmony_ci		if (!attribs[ndx].valid(apiType))
2894e5c31af7Sopenharmony_ci			return false;
2895e5c31af7Sopenharmony_ci
2896e5c31af7Sopenharmony_ci	if (methodInfo.ranged)
2897e5c31af7Sopenharmony_ci	{
2898e5c31af7Sopenharmony_ci		deUint32 maxIndexValue = 0;
2899e5c31af7Sopenharmony_ci		if (indexType == INDEXTYPE_BYTE)
2900e5c31af7Sopenharmony_ci			maxIndexValue = GLValue::getMaxValue(INPUTTYPE_UNSIGNED_BYTE).ub.getValue();
2901e5c31af7Sopenharmony_ci		else if (indexType == INDEXTYPE_SHORT)
2902e5c31af7Sopenharmony_ci			maxIndexValue = GLValue::getMaxValue(INPUTTYPE_UNSIGNED_SHORT).us.getValue();
2903e5c31af7Sopenharmony_ci		else if (indexType == INDEXTYPE_INT)
2904e5c31af7Sopenharmony_ci			maxIndexValue = GLValue::getMaxValue(INPUTTYPE_UNSIGNED_INT).ui.getValue();
2905e5c31af7Sopenharmony_ci		else
2906e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2907e5c31af7Sopenharmony_ci
2908e5c31af7Sopenharmony_ci		if (indexMin > indexMax)
2909e5c31af7Sopenharmony_ci			return false;
2910e5c31af7Sopenharmony_ci		if (indexMin < 0 || indexMax < 0)
2911e5c31af7Sopenharmony_ci			return false;
2912e5c31af7Sopenharmony_ci		if ((deUint32)indexMin > maxIndexValue || (deUint32)indexMax > maxIndexValue)
2913e5c31af7Sopenharmony_ci			return false;
2914e5c31af7Sopenharmony_ci	}
2915e5c31af7Sopenharmony_ci
2916e5c31af7Sopenharmony_ci	if (methodInfo.first && first < 0)
2917e5c31af7Sopenharmony_ci		return false;
2918e5c31af7Sopenharmony_ci
2919e5c31af7Sopenharmony_ci	// GLES2 limits
2920e5c31af7Sopenharmony_ci	if (apiType == glu::ApiType::es(2,0))
2921e5c31af7Sopenharmony_ci	{
2922e5c31af7Sopenharmony_ci		if (drawMethod != gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS && drawMethod != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS)
2923e5c31af7Sopenharmony_ci			return false;
2924e5c31af7Sopenharmony_ci		if (drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS && (indexType != INDEXTYPE_BYTE && indexType != INDEXTYPE_SHORT))
2925e5c31af7Sopenharmony_ci			return false;
2926e5c31af7Sopenharmony_ci	}
2927e5c31af7Sopenharmony_ci
2928e5c31af7Sopenharmony_ci	// Indirect limitations
2929e5c31af7Sopenharmony_ci	if (methodInfo.indirect)
2930e5c31af7Sopenharmony_ci	{
2931e5c31af7Sopenharmony_ci		// Indirect offset alignment
2932e5c31af7Sopenharmony_ci		if (indirectOffset % 4 != 0)
2933e5c31af7Sopenharmony_ci			return false;
2934e5c31af7Sopenharmony_ci
2935e5c31af7Sopenharmony_ci		// All attribute arrays must be stored in a buffer
2936e5c31af7Sopenharmony_ci		for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2937e5c31af7Sopenharmony_ci			if (!attribs[ndx].useDefaultAttribute && attribs[ndx].storage == gls::DrawTestSpec::STORAGE_USER)
2938e5c31af7Sopenharmony_ci				return false;
2939e5c31af7Sopenharmony_ci	}
2940e5c31af7Sopenharmony_ci	if (drawMethod == DRAWMETHOD_DRAWELEMENTS_INDIRECT)
2941e5c31af7Sopenharmony_ci	{
2942e5c31af7Sopenharmony_ci		// index offset must be convertable to firstIndex
2943e5c31af7Sopenharmony_ci		if (indexPointerOffset % gls::DrawTestSpec::indexTypeSize(indexType) != 0)
2944e5c31af7Sopenharmony_ci			return false;
2945e5c31af7Sopenharmony_ci
2946e5c31af7Sopenharmony_ci		// Indices must be in a buffer
2947e5c31af7Sopenharmony_ci		if (indexStorage != STORAGE_BUFFER)
2948e5c31af7Sopenharmony_ci			return false;
2949e5c31af7Sopenharmony_ci	}
2950e5c31af7Sopenharmony_ci
2951e5c31af7Sopenharmony_ci	// Do not allow user pointer in GL core
2952e5c31af7Sopenharmony_ci	if (apiType.getProfile() == glu::PROFILE_CORE)
2953e5c31af7Sopenharmony_ci	{
2954e5c31af7Sopenharmony_ci		if (methodInfo.indexed && indexStorage == DrawTestSpec::STORAGE_USER)
2955e5c31af7Sopenharmony_ci			return false;
2956e5c31af7Sopenharmony_ci	}
2957e5c31af7Sopenharmony_ci
2958e5c31af7Sopenharmony_ci	return true;
2959e5c31af7Sopenharmony_ci}
2960e5c31af7Sopenharmony_ci
2961e5c31af7Sopenharmony_ciDrawTestSpec::CompatibilityTestType DrawTestSpec::isCompatibilityTest (void) const
2962e5c31af7Sopenharmony_ci{
2963e5c31af7Sopenharmony_ci	const MethodInfo methodInfo = getMethodInfo(drawMethod);
2964e5c31af7Sopenharmony_ci
2965e5c31af7Sopenharmony_ci	bool bufferAlignmentBad = false;
2966e5c31af7Sopenharmony_ci	bool strideAlignmentBad = false;
2967e5c31af7Sopenharmony_ci
2968e5c31af7Sopenharmony_ci	// Attribute buffer alignment
2969e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2970e5c31af7Sopenharmony_ci		if (!attribs[ndx].isBufferAligned())
2971e5c31af7Sopenharmony_ci			bufferAlignmentBad = true;
2972e5c31af7Sopenharmony_ci
2973e5c31af7Sopenharmony_ci	// Attribute stride alignment
2974e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)attribs.size(); ++ndx)
2975e5c31af7Sopenharmony_ci		if (!attribs[ndx].isBufferStrideAligned())
2976e5c31af7Sopenharmony_ci			strideAlignmentBad = true;
2977e5c31af7Sopenharmony_ci
2978e5c31af7Sopenharmony_ci	// Index buffer alignment
2979e5c31af7Sopenharmony_ci	if (methodInfo.indexed)
2980e5c31af7Sopenharmony_ci	{
2981e5c31af7Sopenharmony_ci		if (indexStorage == STORAGE_BUFFER)
2982e5c31af7Sopenharmony_ci		{
2983e5c31af7Sopenharmony_ci			int indexSize = 0;
2984e5c31af7Sopenharmony_ci			if (indexType == INDEXTYPE_BYTE)
2985e5c31af7Sopenharmony_ci				indexSize = 1;
2986e5c31af7Sopenharmony_ci			else if (indexType == INDEXTYPE_SHORT)
2987e5c31af7Sopenharmony_ci				indexSize = 2;
2988e5c31af7Sopenharmony_ci			else if (indexType == INDEXTYPE_INT)
2989e5c31af7Sopenharmony_ci				indexSize = 4;
2990e5c31af7Sopenharmony_ci			else
2991e5c31af7Sopenharmony_ci				DE_ASSERT(DE_FALSE);
2992e5c31af7Sopenharmony_ci
2993e5c31af7Sopenharmony_ci			if (indexPointerOffset % indexSize != 0)
2994e5c31af7Sopenharmony_ci				bufferAlignmentBad = true;
2995e5c31af7Sopenharmony_ci		}
2996e5c31af7Sopenharmony_ci	}
2997e5c31af7Sopenharmony_ci
2998e5c31af7Sopenharmony_ci	// \note combination bad alignment & stride is treated as bad offset
2999e5c31af7Sopenharmony_ci	if (bufferAlignmentBad)
3000e5c31af7Sopenharmony_ci		return COMPATIBILITY_UNALIGNED_OFFSET;
3001e5c31af7Sopenharmony_ci	else if (strideAlignmentBad)
3002e5c31af7Sopenharmony_ci		return COMPATIBILITY_UNALIGNED_STRIDE;
3003e5c31af7Sopenharmony_ci	else
3004e5c31af7Sopenharmony_ci		return COMPATIBILITY_NONE;
3005e5c31af7Sopenharmony_ci}
3006e5c31af7Sopenharmony_ci
3007e5c31af7Sopenharmony_cienum PrimitiveClass
3008e5c31af7Sopenharmony_ci{
3009e5c31af7Sopenharmony_ci	PRIMITIVECLASS_POINT = 0,
3010e5c31af7Sopenharmony_ci	PRIMITIVECLASS_LINE,
3011e5c31af7Sopenharmony_ci	PRIMITIVECLASS_TRIANGLE,
3012e5c31af7Sopenharmony_ci
3013e5c31af7Sopenharmony_ci	PRIMITIVECLASS_LAST
3014e5c31af7Sopenharmony_ci};
3015e5c31af7Sopenharmony_ci
3016e5c31af7Sopenharmony_cistatic PrimitiveClass getDrawPrimitiveClass (gls::DrawTestSpec::Primitive primitiveType)
3017e5c31af7Sopenharmony_ci{
3018e5c31af7Sopenharmony_ci	switch (primitiveType)
3019e5c31af7Sopenharmony_ci	{
3020e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_POINTS:
3021e5c31af7Sopenharmony_ci			return PRIMITIVECLASS_POINT;
3022e5c31af7Sopenharmony_ci
3023e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_LINES:
3024e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP:
3025e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_LINE_LOOP:
3026e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:
3027e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:
3028e5c31af7Sopenharmony_ci			return PRIMITIVECLASS_LINE;
3029e5c31af7Sopenharmony_ci
3030e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_TRIANGLES:
3031e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:
3032e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:
3033e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:
3034e5c31af7Sopenharmony_ci		case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:
3035e5c31af7Sopenharmony_ci			return PRIMITIVECLASS_TRIANGLE;
3036e5c31af7Sopenharmony_ci
3037e5c31af7Sopenharmony_ci		default:
3038e5c31af7Sopenharmony_ci			DE_ASSERT(false);
3039e5c31af7Sopenharmony_ci			return PRIMITIVECLASS_LAST;
3040e5c31af7Sopenharmony_ci	}
3041e5c31af7Sopenharmony_ci}
3042e5c31af7Sopenharmony_ci
3043e5c31af7Sopenharmony_cistatic bool containsLineCases (const std::vector<DrawTestSpec>& m_specs)
3044e5c31af7Sopenharmony_ci{
3045e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < (int)m_specs.size(); ++ndx)
3046e5c31af7Sopenharmony_ci	{
3047e5c31af7Sopenharmony_ci		if (getDrawPrimitiveClass(m_specs[ndx].primitive) == PRIMITIVECLASS_LINE)
3048e5c31af7Sopenharmony_ci			return true;
3049e5c31af7Sopenharmony_ci	}
3050e5c31af7Sopenharmony_ci	return false;
3051e5c31af7Sopenharmony_ci}
3052e5c31af7Sopenharmony_ci
3053e5c31af7Sopenharmony_ci// DrawTest
3054e5c31af7Sopenharmony_ci
3055e5c31af7Sopenharmony_ciDrawTest::DrawTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const DrawTestSpec& spec, const char* name, const char* desc)
3056e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, desc)
3057e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
3058e5c31af7Sopenharmony_ci	, m_contextInfo		(DE_NULL)
3059e5c31af7Sopenharmony_ci	, m_refBuffers		(DE_NULL)
3060e5c31af7Sopenharmony_ci	, m_refContext		(DE_NULL)
3061e5c31af7Sopenharmony_ci	, m_glesContext		(DE_NULL)
3062e5c31af7Sopenharmony_ci	, m_glArrayPack		(DE_NULL)
3063e5c31af7Sopenharmony_ci	, m_rrArrayPack		(DE_NULL)
3064e5c31af7Sopenharmony_ci	, m_maxDiffRed		(-1)
3065e5c31af7Sopenharmony_ci	, m_maxDiffGreen	(-1)
3066e5c31af7Sopenharmony_ci	, m_maxDiffBlue		(-1)
3067e5c31af7Sopenharmony_ci	, m_iteration		(0)
3068e5c31af7Sopenharmony_ci	, m_result			()	// \note no per-iteration result logging (only one iteration)
3069e5c31af7Sopenharmony_ci{
3070e5c31af7Sopenharmony_ci	addIteration(spec);
3071e5c31af7Sopenharmony_ci}
3072e5c31af7Sopenharmony_ci
3073e5c31af7Sopenharmony_ciDrawTest::DrawTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc)
3074e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, desc)
3075e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
3076e5c31af7Sopenharmony_ci	, m_contextInfo		(DE_NULL)
3077e5c31af7Sopenharmony_ci	, m_refBuffers		(DE_NULL)
3078e5c31af7Sopenharmony_ci	, m_refContext		(DE_NULL)
3079e5c31af7Sopenharmony_ci	, m_glesContext		(DE_NULL)
3080e5c31af7Sopenharmony_ci	, m_glArrayPack		(DE_NULL)
3081e5c31af7Sopenharmony_ci	, m_rrArrayPack		(DE_NULL)
3082e5c31af7Sopenharmony_ci	, m_maxDiffRed		(-1)
3083e5c31af7Sopenharmony_ci	, m_maxDiffGreen	(-1)
3084e5c31af7Sopenharmony_ci	, m_maxDiffBlue		(-1)
3085e5c31af7Sopenharmony_ci	, m_iteration		(0)
3086e5c31af7Sopenharmony_ci	, m_result			(testCtx.getLog(), "Iteration result: ")
3087e5c31af7Sopenharmony_ci{
3088e5c31af7Sopenharmony_ci}
3089e5c31af7Sopenharmony_ci
3090e5c31af7Sopenharmony_ciDrawTest::~DrawTest	(void)
3091e5c31af7Sopenharmony_ci{
3092e5c31af7Sopenharmony_ci	deinit();
3093e5c31af7Sopenharmony_ci}
3094e5c31af7Sopenharmony_ci
3095e5c31af7Sopenharmony_civoid DrawTest::addIteration (const DrawTestSpec& spec, const char* description)
3096e5c31af7Sopenharmony_ci{
3097e5c31af7Sopenharmony_ci	// Validate spec
3098e5c31af7Sopenharmony_ci	const bool validSpec = spec.valid();
3099e5c31af7Sopenharmony_ci	DE_ASSERT(validSpec);
3100e5c31af7Sopenharmony_ci
3101e5c31af7Sopenharmony_ci	if (!validSpec)
3102e5c31af7Sopenharmony_ci		return;
3103e5c31af7Sopenharmony_ci
3104e5c31af7Sopenharmony_ci	// Check the context type is the same with other iterations
3105e5c31af7Sopenharmony_ci	if (!m_specs.empty())
3106e5c31af7Sopenharmony_ci	{
3107e5c31af7Sopenharmony_ci		const bool validContext = m_specs[0].apiType == spec.apiType;
3108e5c31af7Sopenharmony_ci		DE_ASSERT(validContext);
3109e5c31af7Sopenharmony_ci
3110e5c31af7Sopenharmony_ci		if (!validContext)
3111e5c31af7Sopenharmony_ci			return;
3112e5c31af7Sopenharmony_ci	}
3113e5c31af7Sopenharmony_ci
3114e5c31af7Sopenharmony_ci	m_specs.push_back(spec);
3115e5c31af7Sopenharmony_ci
3116e5c31af7Sopenharmony_ci	if (description)
3117e5c31af7Sopenharmony_ci		m_iteration_descriptions.push_back(std::string(description));
3118e5c31af7Sopenharmony_ci	else
3119e5c31af7Sopenharmony_ci		m_iteration_descriptions.push_back(std::string());
3120e5c31af7Sopenharmony_ci}
3121e5c31af7Sopenharmony_ci
3122e5c31af7Sopenharmony_civoid DrawTest::init (void)
3123e5c31af7Sopenharmony_ci{
3124e5c31af7Sopenharmony_ci	DE_ASSERT(!m_specs.empty());
3125e5c31af7Sopenharmony_ci	DE_ASSERT(contextSupports(m_renderCtx.getType(), m_specs[0].apiType));
3126e5c31af7Sopenharmony_ci
3127e5c31af7Sopenharmony_ci	const int						renderTargetWidth	= de::min(MAX_RENDER_TARGET_SIZE, m_renderCtx.getRenderTarget().getWidth());
3128e5c31af7Sopenharmony_ci	const int						renderTargetHeight	= de::min(MAX_RENDER_TARGET_SIZE, m_renderCtx.getRenderTarget().getHeight());
3129e5c31af7Sopenharmony_ci
3130e5c31af7Sopenharmony_ci	// lines have significantly different rasterization in MSAA mode
3131e5c31af7Sopenharmony_ci	const bool						isLineCase			= containsLineCases(m_specs);
3132e5c31af7Sopenharmony_ci	const bool						isMSAACase			= m_renderCtx.getRenderTarget().getNumSamples() > 1;
3133e5c31af7Sopenharmony_ci	const int						renderTargetSamples	= (isMSAACase && isLineCase) ? (4) : (1);
3134e5c31af7Sopenharmony_ci
3135e5c31af7Sopenharmony_ci	sglr::ReferenceContextLimits	limits				(m_renderCtx);
3136e5c31af7Sopenharmony_ci	bool							useVao				= false;
3137e5c31af7Sopenharmony_ci
3138e5c31af7Sopenharmony_ci	m_glesContext = new sglr::GLContext(m_renderCtx, m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight));
3139e5c31af7Sopenharmony_ci
3140e5c31af7Sopenharmony_ci	if (m_renderCtx.getType().getAPI() == glu::ApiType::es(2,0) || m_renderCtx.getType().getAPI() == glu::ApiType::es(3,0))
3141e5c31af7Sopenharmony_ci		useVao = false;
3142e5c31af7Sopenharmony_ci	else if (contextSupports(m_renderCtx.getType(), glu::ApiType::es(3,1)) || glu::isContextTypeGLCore(m_renderCtx.getType()))
3143e5c31af7Sopenharmony_ci		useVao = true;
3144e5c31af7Sopenharmony_ci	else
3145e5c31af7Sopenharmony_ci		DE_FATAL("Unknown context type");
3146e5c31af7Sopenharmony_ci
3147e5c31af7Sopenharmony_ci	m_refBuffers	= new sglr::ReferenceContextBuffers(m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, renderTargetWidth, renderTargetHeight, renderTargetSamples);
3148e5c31af7Sopenharmony_ci	m_refContext	= new sglr::ReferenceContext(limits, m_refBuffers->getColorbuffer(), m_refBuffers->getDepthbuffer(), m_refBuffers->getStencilbuffer());
3149e5c31af7Sopenharmony_ci
3150e5c31af7Sopenharmony_ci	m_glArrayPack	= new AttributePack(m_testCtx, m_renderCtx, *m_glesContext, tcu::UVec2(renderTargetWidth, renderTargetHeight), useVao, true);
3151e5c31af7Sopenharmony_ci	m_rrArrayPack	= new AttributePack(m_testCtx, m_renderCtx, *m_refContext,  tcu::UVec2(renderTargetWidth, renderTargetHeight), useVao, false);
3152e5c31af7Sopenharmony_ci
3153e5c31af7Sopenharmony_ci	m_maxDiffRed	= deCeilFloatToInt32(256.0f * (6.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().redBits)));
3154e5c31af7Sopenharmony_ci	m_maxDiffGreen	= deCeilFloatToInt32(256.0f * (6.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().greenBits)));
3155e5c31af7Sopenharmony_ci	m_maxDiffBlue	= deCeilFloatToInt32(256.0f * (6.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().blueBits)));
3156e5c31af7Sopenharmony_ci	m_contextInfo	= glu::ContextInfo::create(m_renderCtx);
3157e5c31af7Sopenharmony_ci}
3158e5c31af7Sopenharmony_ci
3159e5c31af7Sopenharmony_civoid DrawTest::deinit (void)
3160e5c31af7Sopenharmony_ci{
3161e5c31af7Sopenharmony_ci	delete m_glArrayPack;
3162e5c31af7Sopenharmony_ci	delete m_rrArrayPack;
3163e5c31af7Sopenharmony_ci	delete m_refBuffers;
3164e5c31af7Sopenharmony_ci	delete m_refContext;
3165e5c31af7Sopenharmony_ci	delete m_glesContext;
3166e5c31af7Sopenharmony_ci	delete m_contextInfo;
3167e5c31af7Sopenharmony_ci
3168e5c31af7Sopenharmony_ci	m_glArrayPack	= DE_NULL;
3169e5c31af7Sopenharmony_ci	m_rrArrayPack	= DE_NULL;
3170e5c31af7Sopenharmony_ci	m_refBuffers	= DE_NULL;
3171e5c31af7Sopenharmony_ci	m_refContext	= DE_NULL;
3172e5c31af7Sopenharmony_ci	m_glesContext	= DE_NULL;
3173e5c31af7Sopenharmony_ci	m_contextInfo	= DE_NULL;
3174e5c31af7Sopenharmony_ci}
3175e5c31af7Sopenharmony_ci
3176e5c31af7Sopenharmony_ciDrawTest::IterateResult DrawTest::iterate (void)
3177e5c31af7Sopenharmony_ci{
3178e5c31af7Sopenharmony_ci	const int					specNdx			= (m_iteration / 2);
3179e5c31af7Sopenharmony_ci	const DrawTestSpec&			spec			= m_specs[specNdx];
3180e5c31af7Sopenharmony_ci
3181e5c31af7Sopenharmony_ci	if (spec.drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX ||
3182e5c31af7Sopenharmony_ci		spec.drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX ||
3183e5c31af7Sopenharmony_ci		spec.drawMethod == DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
3184e5c31af7Sopenharmony_ci	{
3185e5c31af7Sopenharmony_ci		const bool supportsES32orGL45 = contextSupports(m_renderCtx.getType(), glu::ApiType::es(3, 2)) ||
3186e5c31af7Sopenharmony_ci										contextSupports(m_renderCtx.getType(), glu::ApiType::core(4, 5));
3187e5c31af7Sopenharmony_ci		TCU_CHECK_AND_THROW(NotSupportedError, supportsES32orGL45 || m_contextInfo->isExtensionSupported("GL_EXT_draw_elements_base_vertex"), "GL_EXT_draw_elements_base_vertex is not supported.");
3188e5c31af7Sopenharmony_ci	}
3189e5c31af7Sopenharmony_ci
3190e5c31af7Sopenharmony_ci	const bool					drawStep		= (m_iteration % 2) == 0;
3191e5c31af7Sopenharmony_ci	const bool					compareStep		= (m_iteration % 2) == 1;
3192e5c31af7Sopenharmony_ci	const IterateResult			iterateResult	= ((size_t)m_iteration + 1 == m_specs.size()*2) ? (STOP) : (CONTINUE);
3193e5c31af7Sopenharmony_ci	const bool					updateProgram	= (m_iteration == 0) || (drawStep && !checkSpecsShaderCompatible(m_specs[specNdx], m_specs[specNdx-1])); // try to use the same shader in all iterations
3194e5c31af7Sopenharmony_ci	IterationLogSectionEmitter	sectionEmitter	(m_testCtx.getLog(), specNdx, m_specs.size(), m_iteration_descriptions[specNdx], drawStep && m_specs.size()!=1);
3195e5c31af7Sopenharmony_ci
3196e5c31af7Sopenharmony_ci	if (drawStep)
3197e5c31af7Sopenharmony_ci	{
3198e5c31af7Sopenharmony_ci		const MethodInfo	methodInfo				= getMethodInfo(spec.drawMethod);
3199e5c31af7Sopenharmony_ci		const bool			indexed					= methodInfo.indexed;
3200e5c31af7Sopenharmony_ci		const bool			instanced				= methodInfo.instanced;
3201e5c31af7Sopenharmony_ci		const bool			ranged					= methodInfo.ranged;
3202e5c31af7Sopenharmony_ci		const bool			hasFirst				= methodInfo.first;
3203e5c31af7Sopenharmony_ci		const bool			hasBaseVtx				= methodInfo.baseVertex;
3204e5c31af7Sopenharmony_ci
3205e5c31af7Sopenharmony_ci		const size_t		primitiveElementCount	= getElementCount(spec.primitive, spec.primitiveCount);						// !< elements to be drawn
3206e5c31af7Sopenharmony_ci		const int			indexMin				= (ranged) ? (spec.indexMin) : (0);
3207e5c31af7Sopenharmony_ci		const int			firstAddition			= (hasFirst) ? (spec.first) : (0);
3208e5c31af7Sopenharmony_ci		const int			baseVertexAddition		= (hasBaseVtx && spec.baseVertex > 0) ? ( spec.baseVertex) : (0);			// spec.baseVertex > 0 => Create bigger attribute buffer
3209e5c31af7Sopenharmony_ci		const int			indexBase				= (hasBaseVtx && spec.baseVertex < 0) ? (-spec.baseVertex) : (0);			// spec.baseVertex < 0 => Create bigger indices
3210e5c31af7Sopenharmony_ci		const size_t		elementCount			= primitiveElementCount + indexMin + firstAddition + baseVertexAddition;	// !< elements in buffer (buffer should have at least primitiveElementCount ACCESSIBLE (index range, first) elements)
3211e5c31af7Sopenharmony_ci		const int			maxElementIndex			= (int)primitiveElementCount + indexMin + firstAddition - 1;
3212e5c31af7Sopenharmony_ci		const int			indexMax				= de::max(0, (ranged) ? (de::clamp<int>(spec.indexMax, 0, maxElementIndex)) : (maxElementIndex));
3213e5c31af7Sopenharmony_ci		float				coordScale				= getCoordScale(spec);
3214e5c31af7Sopenharmony_ci		float				colorScale				= getColorScale(spec);
3215e5c31af7Sopenharmony_ci
3216e5c31af7Sopenharmony_ci		rr::GenericVec4		nullAttribValue;
3217e5c31af7Sopenharmony_ci
3218e5c31af7Sopenharmony_ci		// Log info
3219e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::Message << spec.getMultilineDesc() << TestLog::EndMessage;
3220e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::Message << TestLog::EndMessage; // extra line for clarity
3221e5c31af7Sopenharmony_ci
3222e5c31af7Sopenharmony_ci		// Data
3223e5c31af7Sopenharmony_ci
3224e5c31af7Sopenharmony_ci		m_glArrayPack->clearArrays();
3225e5c31af7Sopenharmony_ci		m_rrArrayPack->clearArrays();
3226e5c31af7Sopenharmony_ci
3227e5c31af7Sopenharmony_ci		for (int attribNdx = 0; attribNdx < (int)spec.attribs.size(); attribNdx++)
3228e5c31af7Sopenharmony_ci		{
3229e5c31af7Sopenharmony_ci			DrawTestSpec::AttributeSpec attribSpec		= spec.attribs[attribNdx];
3230e5c31af7Sopenharmony_ci			const bool					isPositionAttr	= (attribNdx == 0) || (attribSpec.additionalPositionAttribute);
3231e5c31af7Sopenharmony_ci
3232e5c31af7Sopenharmony_ci			if (attribSpec.useDefaultAttribute)
3233e5c31af7Sopenharmony_ci			{
3234e5c31af7Sopenharmony_ci				const int		seed		= 10 * attribSpec.hash() + 100 * spec.hash() + attribNdx;
3235e5c31af7Sopenharmony_ci				rr::GenericVec4 attribValue = RandomArrayGenerator::generateAttributeValue(seed, attribSpec.inputType);
3236e5c31af7Sopenharmony_ci
3237e5c31af7Sopenharmony_ci				m_glArrayPack->newArray(DrawTestSpec::STORAGE_USER);
3238e5c31af7Sopenharmony_ci				m_rrArrayPack->newArray(DrawTestSpec::STORAGE_USER);
3239e5c31af7Sopenharmony_ci
3240e5c31af7Sopenharmony_ci				m_glArrayPack->getArray(attribNdx)->setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr, false);
3241e5c31af7Sopenharmony_ci				m_rrArrayPack->getArray(attribNdx)->setupArray(false, 0, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, false, 0, 0, attribValue, isPositionAttr, false);
3242e5c31af7Sopenharmony_ci			}
3243e5c31af7Sopenharmony_ci			else
3244e5c31af7Sopenharmony_ci			{
3245e5c31af7Sopenharmony_ci				const int					seed					= attribSpec.hash() + 100 * spec.hash() + attribNdx;
3246e5c31af7Sopenharmony_ci				const size_t				elementSize				= attribSpec.componentCount * DrawTestSpec::inputTypeSize(attribSpec.inputType);
3247e5c31af7Sopenharmony_ci				const size_t				stride					= (attribSpec.stride == 0) ? (elementSize) : (attribSpec.stride);
3248e5c31af7Sopenharmony_ci				const size_t				evaluatedElementCount	= (instanced && attribSpec.instanceDivisor > 0) ? (spec.instanceCount / attribSpec.instanceDivisor + 1) : (elementCount);
3249e5c31af7Sopenharmony_ci				const size_t				referencedElementCount	= (ranged) ? (de::max<size_t>(evaluatedElementCount, spec.indexMax + 1)) : (evaluatedElementCount);
3250e5c31af7Sopenharmony_ci				const size_t				bufferSize				= attribSpec.offset + stride * (referencedElementCount - 1) + elementSize;
3251e5c31af7Sopenharmony_ci				const char*					data					= RandomArrayGenerator::generateArray(seed, (int)referencedElementCount, attribSpec.componentCount, attribSpec.offset, (int)stride, attribSpec.inputType);
3252e5c31af7Sopenharmony_ci
3253e5c31af7Sopenharmony_ci				try
3254e5c31af7Sopenharmony_ci				{
3255e5c31af7Sopenharmony_ci					m_glArrayPack->newArray(attribSpec.storage);
3256e5c31af7Sopenharmony_ci					m_rrArrayPack->newArray(attribSpec.storage);
3257e5c31af7Sopenharmony_ci
3258e5c31af7Sopenharmony_ci					m_glArrayPack->getArray(attribNdx)->data(DrawTestSpec::TARGET_ARRAY, bufferSize, data, attribSpec.usage);
3259e5c31af7Sopenharmony_ci					m_rrArrayPack->getArray(attribNdx)->data(DrawTestSpec::TARGET_ARRAY, bufferSize, data, attribSpec.usage);
3260e5c31af7Sopenharmony_ci
3261e5c31af7Sopenharmony_ci					m_glArrayPack->getArray(attribNdx)->setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr, attribSpec.bgraComponentOrder);
3262e5c31af7Sopenharmony_ci					m_rrArrayPack->getArray(attribNdx)->setupArray(true, attribSpec.offset, attribSpec.componentCount, attribSpec.inputType, attribSpec.outputType, attribSpec.normalize, attribSpec.stride, attribSpec.instanceDivisor, nullAttribValue, isPositionAttr, attribSpec.bgraComponentOrder);
3263e5c31af7Sopenharmony_ci
3264e5c31af7Sopenharmony_ci					delete [] data;
3265e5c31af7Sopenharmony_ci					data = NULL;
3266e5c31af7Sopenharmony_ci				}
3267e5c31af7Sopenharmony_ci				catch (...)
3268e5c31af7Sopenharmony_ci				{
3269e5c31af7Sopenharmony_ci					delete [] data;
3270e5c31af7Sopenharmony_ci					throw;
3271e5c31af7Sopenharmony_ci				}
3272e5c31af7Sopenharmony_ci			}
3273e5c31af7Sopenharmony_ci		}
3274e5c31af7Sopenharmony_ci
3275e5c31af7Sopenharmony_ci		// Shader program
3276e5c31af7Sopenharmony_ci		if (updateProgram)
3277e5c31af7Sopenharmony_ci		{
3278e5c31af7Sopenharmony_ci			m_glArrayPack->updateProgram();
3279e5c31af7Sopenharmony_ci			m_rrArrayPack->updateProgram();
3280e5c31af7Sopenharmony_ci		}
3281e5c31af7Sopenharmony_ci
3282e5c31af7Sopenharmony_ci		// Draw
3283e5c31af7Sopenharmony_ci		try
3284e5c31af7Sopenharmony_ci		{
3285e5c31af7Sopenharmony_ci			// indices
3286e5c31af7Sopenharmony_ci			if (indexed)
3287e5c31af7Sopenharmony_ci			{
3288e5c31af7Sopenharmony_ci				const int		seed				= spec.hash();
3289e5c31af7Sopenharmony_ci				const size_t	indexElementSize	= DrawTestSpec::indexTypeSize(spec.indexType);
3290e5c31af7Sopenharmony_ci				const size_t	indexArraySize		= spec.indexPointerOffset + indexElementSize * elementCount;
3291e5c31af7Sopenharmony_ci				const char*		indexArray			= RandomArrayGenerator::generateIndices(seed, (int)elementCount, spec.indexType, spec.indexPointerOffset, indexMin, indexMax, indexBase);
3292e5c31af7Sopenharmony_ci				const char*		indexPointerBase	= (spec.indexStorage == DrawTestSpec::STORAGE_USER) ? (indexArray) : ((char*)DE_NULL);
3293e5c31af7Sopenharmony_ci				const char*		indexPointer		= indexPointerBase + spec.indexPointerOffset;
3294e5c31af7Sopenharmony_ci
3295e5c31af7Sopenharmony_ci				de::UniquePtr<AttributeArray> glArray	(new AttributeArray(spec.indexStorage, *m_glesContext));
3296e5c31af7Sopenharmony_ci				de::UniquePtr<AttributeArray> rrArray	(new AttributeArray(spec.indexStorage, *m_refContext));
3297e5c31af7Sopenharmony_ci
3298e5c31af7Sopenharmony_ci				try
3299e5c31af7Sopenharmony_ci				{
3300e5c31af7Sopenharmony_ci					glArray->data(DrawTestSpec::TARGET_ELEMENT_ARRAY, indexArraySize, indexArray, DrawTestSpec::USAGE_STATIC_DRAW);
3301e5c31af7Sopenharmony_ci					rrArray->data(DrawTestSpec::TARGET_ELEMENT_ARRAY, indexArraySize, indexArray, DrawTestSpec::USAGE_STATIC_DRAW);
3302e5c31af7Sopenharmony_ci
3303e5c31af7Sopenharmony_ci					m_glArrayPack->render(spec.primitive, spec.drawMethod, 0, (int)primitiveElementCount, spec.indexType, indexPointer, spec.indexMin, spec.indexMax, spec.instanceCount, spec.indirectOffset, spec.baseVertex, coordScale, colorScale, glArray.get());
3304e5c31af7Sopenharmony_ci					m_rrArrayPack->render(spec.primitive, spec.drawMethod, 0, (int)primitiveElementCount, spec.indexType, indexPointer, spec.indexMin, spec.indexMax, spec.instanceCount, spec.indirectOffset, spec.baseVertex, coordScale, colorScale, rrArray.get());
3305e5c31af7Sopenharmony_ci
3306e5c31af7Sopenharmony_ci					delete [] indexArray;
3307e5c31af7Sopenharmony_ci					indexArray = NULL;
3308e5c31af7Sopenharmony_ci				}
3309e5c31af7Sopenharmony_ci				catch (...)
3310e5c31af7Sopenharmony_ci				{
3311e5c31af7Sopenharmony_ci					delete [] indexArray;
3312e5c31af7Sopenharmony_ci					throw;
3313e5c31af7Sopenharmony_ci				}
3314e5c31af7Sopenharmony_ci			}
3315e5c31af7Sopenharmony_ci			else
3316e5c31af7Sopenharmony_ci			{
3317e5c31af7Sopenharmony_ci				m_glArrayPack->render(spec.primitive, spec.drawMethod, spec.first, (int)primitiveElementCount, DrawTestSpec::INDEXTYPE_LAST, DE_NULL, 0, 0, spec.instanceCount, spec.indirectOffset, 0, coordScale, colorScale, DE_NULL);
3318e5c31af7Sopenharmony_ci				m_testCtx.touchWatchdog();
3319e5c31af7Sopenharmony_ci				m_rrArrayPack->render(spec.primitive, spec.drawMethod, spec.first, (int)primitiveElementCount, DrawTestSpec::INDEXTYPE_LAST, DE_NULL, 0, 0, spec.instanceCount, spec.indirectOffset, 0, coordScale, colorScale, DE_NULL);
3320e5c31af7Sopenharmony_ci			}
3321e5c31af7Sopenharmony_ci		}
3322e5c31af7Sopenharmony_ci		catch (glu::Error& err)
3323e5c31af7Sopenharmony_ci		{
3324e5c31af7Sopenharmony_ci			// GL Errors are ok if the mode is not properly aligned
3325e5c31af7Sopenharmony_ci
3326e5c31af7Sopenharmony_ci			const DrawTestSpec::CompatibilityTestType ctype = spec.isCompatibilityTest();
3327e5c31af7Sopenharmony_ci
3328e5c31af7Sopenharmony_ci			m_testCtx.getLog() << TestLog::Message << "Got error: " << err.what() << TestLog::EndMessage;
3329e5c31af7Sopenharmony_ci
3330e5c31af7Sopenharmony_ci			if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET)
3331e5c31af7Sopenharmony_ci				m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
3332e5c31af7Sopenharmony_ci			else if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
3333e5c31af7Sopenharmony_ci				m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
3334e5c31af7Sopenharmony_ci			else
3335e5c31af7Sopenharmony_ci				throw;
3336e5c31af7Sopenharmony_ci		}
3337e5c31af7Sopenharmony_ci	}
3338e5c31af7Sopenharmony_ci	else if (compareStep)
3339e5c31af7Sopenharmony_ci	{
3340e5c31af7Sopenharmony_ci		if (!compare(spec.primitive))
3341e5c31af7Sopenharmony_ci		{
3342e5c31af7Sopenharmony_ci			const DrawTestSpec::CompatibilityTestType ctype = spec.isCompatibilityTest();
3343e5c31af7Sopenharmony_ci
3344e5c31af7Sopenharmony_ci			if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET)
3345e5c31af7Sopenharmony_ci				m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
3346e5c31af7Sopenharmony_ci			else if (ctype == DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
3347e5c31af7Sopenharmony_ci				m_result.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
3348e5c31af7Sopenharmony_ci			else
3349e5c31af7Sopenharmony_ci				m_result.addResult(QP_TEST_RESULT_FAIL, "Image comparison failed.");
3350e5c31af7Sopenharmony_ci		}
3351e5c31af7Sopenharmony_ci	}
3352e5c31af7Sopenharmony_ci	else
3353e5c31af7Sopenharmony_ci	{
3354e5c31af7Sopenharmony_ci		DE_ASSERT(false);
3355e5c31af7Sopenharmony_ci		return STOP;
3356e5c31af7Sopenharmony_ci	}
3357e5c31af7Sopenharmony_ci
3358e5c31af7Sopenharmony_ci	m_result.setTestContextResult(m_testCtx);
3359e5c31af7Sopenharmony_ci
3360e5c31af7Sopenharmony_ci	m_iteration++;
3361e5c31af7Sopenharmony_ci	return iterateResult;
3362e5c31af7Sopenharmony_ci}
3363e5c31af7Sopenharmony_ci
3364e5c31af7Sopenharmony_cistatic bool isBlack (const tcu::RGBA& c)
3365e5c31af7Sopenharmony_ci{
3366e5c31af7Sopenharmony_ci	// ignore alpha channel
3367e5c31af7Sopenharmony_ci	return c.getRed() == 0 && c.getGreen() == 0 && c.getBlue() == 0;
3368e5c31af7Sopenharmony_ci}
3369e5c31af7Sopenharmony_ci
3370e5c31af7Sopenharmony_cistatic bool isEdgeTripletComponent (int c1, int c2, int c3, int renderTargetDifference)
3371e5c31af7Sopenharmony_ci{
3372e5c31af7Sopenharmony_ci	const int	roundingDifference	= 2 * renderTargetDifference; // src and dst pixels rounded to different directions
3373e5c31af7Sopenharmony_ci	const int	d1					= c2 - c1;
3374e5c31af7Sopenharmony_ci	const int	d2					= c3 - c2;
3375e5c31af7Sopenharmony_ci	const int	rampDiff			= de::abs(d2 - d1);
3376e5c31af7Sopenharmony_ci
3377e5c31af7Sopenharmony_ci	return rampDiff > roundingDifference;
3378e5c31af7Sopenharmony_ci}
3379e5c31af7Sopenharmony_ci
3380e5c31af7Sopenharmony_cistatic bool isEdgeTriplet (const tcu::RGBA& c1, const tcu::RGBA& c2, const tcu::RGBA& c3, const tcu::IVec3& renderTargetThreshold)
3381e5c31af7Sopenharmony_ci{
3382e5c31af7Sopenharmony_ci	// black (background color) and non-black is always an edge
3383e5c31af7Sopenharmony_ci	{
3384e5c31af7Sopenharmony_ci		const bool b1 = isBlack(c1);
3385e5c31af7Sopenharmony_ci		const bool b2 = isBlack(c2);
3386e5c31af7Sopenharmony_ci		const bool b3 = isBlack(c3);
3387e5c31af7Sopenharmony_ci
3388e5c31af7Sopenharmony_ci		// both pixels with coverage and pixels without coverage
3389e5c31af7Sopenharmony_ci		if ((b1 && b2 && b3) == false && (b1 || b2 || b3) == true)
3390e5c31af7Sopenharmony_ci			return true;
3391e5c31af7Sopenharmony_ci		// all black
3392e5c31af7Sopenharmony_ci		if (b1 && b2 && b3)
3393e5c31af7Sopenharmony_ci			return false;
3394e5c31af7Sopenharmony_ci		// all with coverage
3395e5c31af7Sopenharmony_ci		DE_ASSERT(!b1 && !b2 && !b3);
3396e5c31af7Sopenharmony_ci	}
3397e5c31af7Sopenharmony_ci
3398e5c31af7Sopenharmony_ci	// Color is always linearly interpolated => component values change nearly linearly
3399e5c31af7Sopenharmony_ci	// in any constant direction on triangle hull. (df/dx ~= C).
3400e5c31af7Sopenharmony_ci
3401e5c31af7Sopenharmony_ci	// Edge detection (this function) is run against the reference image
3402e5c31af7Sopenharmony_ci	// => no dithering to worry about
3403e5c31af7Sopenharmony_ci
3404e5c31af7Sopenharmony_ci	return	isEdgeTripletComponent(c1.getRed(),		c2.getRed(),	c3.getRed(),	renderTargetThreshold.x())	||
3405e5c31af7Sopenharmony_ci			isEdgeTripletComponent(c1.getGreen(),	c2.getGreen(),	c3.getGreen(),	renderTargetThreshold.y())	||
3406e5c31af7Sopenharmony_ci			isEdgeTripletComponent(c1.getBlue(),	c2.getBlue(),	c3.getBlue(),	renderTargetThreshold.z());
3407e5c31af7Sopenharmony_ci}
3408e5c31af7Sopenharmony_ci
3409e5c31af7Sopenharmony_cistatic bool pixelNearEdge (int x, int y, const tcu::Surface& ref, const tcu::IVec3& renderTargetThreshold)
3410e5c31af7Sopenharmony_ci{
3411e5c31af7Sopenharmony_ci	// should not be called for edge pixels
3412e5c31af7Sopenharmony_ci	DE_ASSERT(x >= 1 && x <= ref.getWidth()-2);
3413e5c31af7Sopenharmony_ci	DE_ASSERT(y >= 1 && y <= ref.getHeight()-2);
3414e5c31af7Sopenharmony_ci
3415e5c31af7Sopenharmony_ci	// horizontal
3416e5c31af7Sopenharmony_ci
3417e5c31af7Sopenharmony_ci	for (int dy = -1; dy < 2; ++dy)
3418e5c31af7Sopenharmony_ci	{
3419e5c31af7Sopenharmony_ci		const tcu::RGBA c1 = ref.getPixel(x-1, y+dy);
3420e5c31af7Sopenharmony_ci		const tcu::RGBA c2 = ref.getPixel(x,   y+dy);
3421e5c31af7Sopenharmony_ci		const tcu::RGBA c3 = ref.getPixel(x+1, y+dy);
3422e5c31af7Sopenharmony_ci		if (isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
3423e5c31af7Sopenharmony_ci			return true;
3424e5c31af7Sopenharmony_ci	}
3425e5c31af7Sopenharmony_ci
3426e5c31af7Sopenharmony_ci	// vertical
3427e5c31af7Sopenharmony_ci
3428e5c31af7Sopenharmony_ci	for (int dx = -1; dx < 2; ++dx)
3429e5c31af7Sopenharmony_ci	{
3430e5c31af7Sopenharmony_ci		const tcu::RGBA c1 = ref.getPixel(x+dx, y-1);
3431e5c31af7Sopenharmony_ci		const tcu::RGBA c2 = ref.getPixel(x+dx, y);
3432e5c31af7Sopenharmony_ci		const tcu::RGBA c3 = ref.getPixel(x+dx, y+1);
3433e5c31af7Sopenharmony_ci		if (isEdgeTriplet(c1, c2, c3, renderTargetThreshold))
3434e5c31af7Sopenharmony_ci			return true;
3435e5c31af7Sopenharmony_ci	}
3436e5c31af7Sopenharmony_ci
3437e5c31af7Sopenharmony_ci	return false;
3438e5c31af7Sopenharmony_ci}
3439e5c31af7Sopenharmony_ci
3440e5c31af7Sopenharmony_cistatic deUint32 getVisualizationGrayscaleColor (const tcu::RGBA& c)
3441e5c31af7Sopenharmony_ci{
3442e5c31af7Sopenharmony_ci	// make triangle coverage and error pixels obvious by converting coverage to grayscale
3443e5c31af7Sopenharmony_ci	if (isBlack(c))
3444e5c31af7Sopenharmony_ci		return 0;
3445e5c31af7Sopenharmony_ci	else
3446e5c31af7Sopenharmony_ci		return 50u + (deUint32)(c.getRed() + c.getBlue() + c.getGreen()) / 8u;
3447e5c31af7Sopenharmony_ci}
3448e5c31af7Sopenharmony_ci
3449e5c31af7Sopenharmony_cistatic bool pixelNearLineIntersection (int x, int y, const tcu::Surface& target)
3450e5c31af7Sopenharmony_ci{
3451e5c31af7Sopenharmony_ci	// should not be called for edge pixels
3452e5c31af7Sopenharmony_ci	DE_ASSERT(x >= 1 && x <= target.getWidth()-2);
3453e5c31af7Sopenharmony_ci	DE_ASSERT(y >= 1 && y <= target.getHeight()-2);
3454e5c31af7Sopenharmony_ci
3455e5c31af7Sopenharmony_ci	int coveredPixels = 0;
3456e5c31af7Sopenharmony_ci
3457e5c31af7Sopenharmony_ci	for (int dy = -1; dy < 2; dy++)
3458e5c31af7Sopenharmony_ci	for (int dx = -1; dx < 2; dx++)
3459e5c31af7Sopenharmony_ci	{
3460e5c31af7Sopenharmony_ci		const bool targetCoverage = !isBlack(target.getPixel(x+dx, y+dy));
3461e5c31af7Sopenharmony_ci		if (targetCoverage)
3462e5c31af7Sopenharmony_ci		{
3463e5c31af7Sopenharmony_ci			++coveredPixels;
3464e5c31af7Sopenharmony_ci
3465e5c31af7Sopenharmony_ci			// A single thin line cannot have more than 3 covered pixels in a 3x3 area
3466e5c31af7Sopenharmony_ci			if (coveredPixels >= 4)
3467e5c31af7Sopenharmony_ci				return true;
3468e5c31af7Sopenharmony_ci		}
3469e5c31af7Sopenharmony_ci	}
3470e5c31af7Sopenharmony_ci
3471e5c31af7Sopenharmony_ci	return false;
3472e5c31af7Sopenharmony_ci}
3473e5c31af7Sopenharmony_ci
3474e5c31af7Sopenharmony_cistatic inline bool colorsEqual (const tcu::RGBA& colorA, const tcu::RGBA& colorB, const tcu::IVec3& compareThreshold)
3475e5c31af7Sopenharmony_ci{
3476e5c31af7Sopenharmony_ci	enum
3477e5c31af7Sopenharmony_ci	{
3478e5c31af7Sopenharmony_ci		TCU_RGBA_RGB_MASK = tcu::RGBA::RED_MASK | tcu::RGBA::GREEN_MASK | tcu::RGBA::BLUE_MASK
3479e5c31af7Sopenharmony_ci	};
3480e5c31af7Sopenharmony_ci
3481e5c31af7Sopenharmony_ci	return tcu::compareThresholdMasked(colorA, colorB, tcu::RGBA(compareThreshold.x(), compareThreshold.y(), compareThreshold.z(), 0), TCU_RGBA_RGB_MASK);
3482e5c31af7Sopenharmony_ci}
3483e5c31af7Sopenharmony_ci
3484e5c31af7Sopenharmony_ci// search 3x3 are for matching color
3485e5c31af7Sopenharmony_cistatic bool pixelNeighborhoodContainsColor (const tcu::Surface& target, int x, int y, const tcu::RGBA& color, const tcu::IVec3& compareThreshold)
3486e5c31af7Sopenharmony_ci{
3487e5c31af7Sopenharmony_ci	// should not be called for edge pixels
3488e5c31af7Sopenharmony_ci	DE_ASSERT(x >= 1 && x <= target.getWidth()-2);
3489e5c31af7Sopenharmony_ci	DE_ASSERT(y >= 1 && y <= target.getHeight()-2);
3490e5c31af7Sopenharmony_ci
3491e5c31af7Sopenharmony_ci	for (int dy = -1; dy < 2; dy++)
3492e5c31af7Sopenharmony_ci	for (int dx = -1; dx < 2; dx++)
3493e5c31af7Sopenharmony_ci	{
3494e5c31af7Sopenharmony_ci		const tcu::RGBA	targetCmpPixel = target.getPixel(x+dx, y+dy);
3495e5c31af7Sopenharmony_ci		if (colorsEqual(color, targetCmpPixel, compareThreshold))
3496e5c31af7Sopenharmony_ci			return true;
3497e5c31af7Sopenharmony_ci	}
3498e5c31af7Sopenharmony_ci
3499e5c31af7Sopenharmony_ci	return false;
3500e5c31af7Sopenharmony_ci}
3501e5c31af7Sopenharmony_ci
3502e5c31af7Sopenharmony_ci// search 3x3 are for matching coverage (coverage == (color != background color))
3503e5c31af7Sopenharmony_cistatic bool pixelNeighborhoodContainsCoverage (const tcu::Surface& target, int x, int y, bool coverage)
3504e5c31af7Sopenharmony_ci{
3505e5c31af7Sopenharmony_ci	// should not be called for edge pixels
3506e5c31af7Sopenharmony_ci	DE_ASSERT(x >= 1 && x <= target.getWidth()-2);
3507e5c31af7Sopenharmony_ci	DE_ASSERT(y >= 1 && y <= target.getHeight()-2);
3508e5c31af7Sopenharmony_ci
3509e5c31af7Sopenharmony_ci	for (int dy = -1; dy < 2; dy++)
3510e5c31af7Sopenharmony_ci	for (int dx = -1; dx < 2; dx++)
3511e5c31af7Sopenharmony_ci	{
3512e5c31af7Sopenharmony_ci		const bool targetCmpCoverage = !isBlack(target.getPixel(x+dx, y+dy));
3513e5c31af7Sopenharmony_ci		if (targetCmpCoverage == coverage)
3514e5c31af7Sopenharmony_ci			return true;
3515e5c31af7Sopenharmony_ci	}
3516e5c31af7Sopenharmony_ci
3517e5c31af7Sopenharmony_ci	return false;
3518e5c31af7Sopenharmony_ci}
3519e5c31af7Sopenharmony_ci
3520e5c31af7Sopenharmony_cistatic bool edgeRelaxedImageCompare (tcu::TestLog& log, const char* imageSetName, const char* imageSetDesc, const tcu::Surface& reference, const tcu::Surface& result, const tcu::IVec3& compareThreshold, const tcu::IVec3& renderTargetThreshold, int maxAllowedInvalidPixels)
3521e5c31af7Sopenharmony_ci{
3522e5c31af7Sopenharmony_ci	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
3523e5c31af7Sopenharmony_ci
3524e5c31af7Sopenharmony_ci	const tcu::IVec4				green						(0, 255, 0, 255);
3525e5c31af7Sopenharmony_ci	const tcu::IVec4				red							(255, 0, 0, 255);
3526e5c31af7Sopenharmony_ci	const int						width						= reference.getWidth();
3527e5c31af7Sopenharmony_ci	const int						height						= reference.getHeight();
3528e5c31af7Sopenharmony_ci	tcu::TextureLevel				errorMask					(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), width, height);
3529e5c31af7Sopenharmony_ci	const tcu::PixelBufferAccess	errorAccess					= errorMask.getAccess();
3530e5c31af7Sopenharmony_ci	int								numFailingPixels			= 0;
3531e5c31af7Sopenharmony_ci
3532e5c31af7Sopenharmony_ci	// clear errormask edges which would otherwise be transparent
3533e5c31af7Sopenharmony_ci
3534e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, 0,			0,			width,	1),			green);
3535e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, 0,			height-1,	width,	1),			green);
3536e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, 0,			0,			1,		height),	green);
3537e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, width-1,		0,			1,		height),	green);
3538e5c31af7Sopenharmony_ci
3539e5c31af7Sopenharmony_ci	// skip edge pixels since coverage on edge cannot be verified
3540e5c31af7Sopenharmony_ci
3541e5c31af7Sopenharmony_ci	for (int y = 1; y < height - 1; ++y)
3542e5c31af7Sopenharmony_ci	for (int x = 1; x < width - 1; ++x)
3543e5c31af7Sopenharmony_ci	{
3544e5c31af7Sopenharmony_ci		const tcu::RGBA	refPixel			= reference.getPixel(x, y);
3545e5c31af7Sopenharmony_ci		const tcu::RGBA	screenPixel			= result.getPixel(x, y);
3546e5c31af7Sopenharmony_ci		const bool		directMatch			= colorsEqual(refPixel, screenPixel, compareThreshold);
3547e5c31af7Sopenharmony_ci		const bool		isOkReferencePixel	= directMatch || pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold);			// screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
3548e5c31af7Sopenharmony_ci		const bool		isOkScreenPixel		= directMatch || pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold);	// reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
3549e5c31af7Sopenharmony_ci
3550e5c31af7Sopenharmony_ci		if (isOkScreenPixel && isOkReferencePixel)
3551e5c31af7Sopenharmony_ci		{
3552e5c31af7Sopenharmony_ci			// pixel valid, write greenish pixels to make the result image easier to read
3553e5c31af7Sopenharmony_ci			const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3554e5c31af7Sopenharmony_ci			errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3555e5c31af7Sopenharmony_ci		}
3556e5c31af7Sopenharmony_ci		else if (!pixelNearEdge(x, y, reference, renderTargetThreshold))
3557e5c31af7Sopenharmony_ci		{
3558e5c31af7Sopenharmony_ci			// non-edge pixel values must be within threshold of the reference values
3559e5c31af7Sopenharmony_ci			errorAccess.setPixel(red, x, y);
3560e5c31af7Sopenharmony_ci			++numFailingPixels;
3561e5c31af7Sopenharmony_ci		}
3562e5c31af7Sopenharmony_ci		else
3563e5c31af7Sopenharmony_ci		{
3564e5c31af7Sopenharmony_ci			// we are on/near an edge, verify only coverage (coverage == not background colored)
3565e5c31af7Sopenharmony_ci			const bool	referenceCoverage		= !isBlack(refPixel);
3566e5c31af7Sopenharmony_ci			const bool	screenCoverage			= !isBlack(screenPixel);
3567e5c31af7Sopenharmony_ci			const bool	isOkReferenceCoverage	= pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage);	// Check reference pixel against screen pixel
3568e5c31af7Sopenharmony_ci			const bool	isOkScreenCoverage		= pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage);	// Check screen pixels against reference pixel
3569e5c31af7Sopenharmony_ci
3570e5c31af7Sopenharmony_ci			if (isOkScreenCoverage && isOkReferenceCoverage)
3571e5c31af7Sopenharmony_ci			{
3572e5c31af7Sopenharmony_ci				// pixel valid, write greenish pixels to make the result image easier to read
3573e5c31af7Sopenharmony_ci				const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3574e5c31af7Sopenharmony_ci				errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3575e5c31af7Sopenharmony_ci			}
3576e5c31af7Sopenharmony_ci			else
3577e5c31af7Sopenharmony_ci			{
3578e5c31af7Sopenharmony_ci				// coverage does not match
3579e5c31af7Sopenharmony_ci				errorAccess.setPixel(red, x, y);
3580e5c31af7Sopenharmony_ci				++numFailingPixels;
3581e5c31af7Sopenharmony_ci			}
3582e5c31af7Sopenharmony_ci		}
3583e5c31af7Sopenharmony_ci	}
3584e5c31af7Sopenharmony_ci
3585e5c31af7Sopenharmony_ci	log	<< TestLog::Message
3586e5c31af7Sopenharmony_ci		<< "Comparing images:\n"
3587e5c31af7Sopenharmony_ci		<< "\tallowed deviation in pixel positions = 1\n"
3588e5c31af7Sopenharmony_ci		<< "\tnumber of allowed invalid pixels = " << maxAllowedInvalidPixels << "\n"
3589e5c31af7Sopenharmony_ci		<< "\tnumber of invalid pixels = " << numFailingPixels
3590e5c31af7Sopenharmony_ci		<< TestLog::EndMessage;
3591e5c31af7Sopenharmony_ci
3592e5c31af7Sopenharmony_ci	if (numFailingPixels > maxAllowedInvalidPixels)
3593e5c31af7Sopenharmony_ci	{
3594e5c31af7Sopenharmony_ci		log << TestLog::Message
3595e5c31af7Sopenharmony_ci			<< "Image comparison failed. Color threshold = (" << compareThreshold.x() << ", " << compareThreshold.y() << ", " << compareThreshold.z() << ")"
3596e5c31af7Sopenharmony_ci			<< TestLog::EndMessage
3597e5c31af7Sopenharmony_ci			<< TestLog::ImageSet(imageSetName, imageSetDesc)
3598e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result)
3599e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference)
3600e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
3601e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
3602e5c31af7Sopenharmony_ci
3603e5c31af7Sopenharmony_ci		return false;
3604e5c31af7Sopenharmony_ci	}
3605e5c31af7Sopenharmony_ci	else
3606e5c31af7Sopenharmony_ci	{
3607e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
3608e5c31af7Sopenharmony_ci			<< TestLog::Image("Result", "Result", result)
3609e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
3610e5c31af7Sopenharmony_ci
3611e5c31af7Sopenharmony_ci		return true;
3612e5c31af7Sopenharmony_ci	}
3613e5c31af7Sopenharmony_ci}
3614e5c31af7Sopenharmony_ci
3615e5c31af7Sopenharmony_cistatic bool intersectionRelaxedLineImageCompare (tcu::TestLog& log, const char* imageSetName, const char* imageSetDesc, const tcu::Surface& reference, const tcu::Surface& result, const tcu::IVec3& compareThreshold, int maxAllowedInvalidPixels)
3616e5c31af7Sopenharmony_ci{
3617e5c31af7Sopenharmony_ci	DE_ASSERT(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight());
3618e5c31af7Sopenharmony_ci
3619e5c31af7Sopenharmony_ci	const tcu::IVec4				green						(0, 255, 0, 255);
3620e5c31af7Sopenharmony_ci	const tcu::IVec4				red							(255, 0, 0, 255);
3621e5c31af7Sopenharmony_ci	const int						width						= reference.getWidth();
3622e5c31af7Sopenharmony_ci	const int						height						= reference.getHeight();
3623e5c31af7Sopenharmony_ci	tcu::TextureLevel				errorMask					(tcu::TextureFormat(tcu::TextureFormat::RGB, tcu::TextureFormat::UNORM_INT8), width, height);
3624e5c31af7Sopenharmony_ci	const tcu::PixelBufferAccess	errorAccess					= errorMask.getAccess();
3625e5c31af7Sopenharmony_ci	int								numFailingPixels			= 0;
3626e5c31af7Sopenharmony_ci
3627e5c31af7Sopenharmony_ci	// clear errormask edges which would otherwise be transparent
3628e5c31af7Sopenharmony_ci
3629e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, 0,			0,			width,	1),			green);
3630e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, 0,			height-1,	width,	1),			green);
3631e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, 0,			0,			1,		height),	green);
3632e5c31af7Sopenharmony_ci	tcu::clear(tcu::getSubregion(errorAccess, width-1,		0,			1,		height),	green);
3633e5c31af7Sopenharmony_ci
3634e5c31af7Sopenharmony_ci	// skip edge pixels since coverage on edge cannot be verified
3635e5c31af7Sopenharmony_ci
3636e5c31af7Sopenharmony_ci	for (int y = 1; y < height - 1; ++y)
3637e5c31af7Sopenharmony_ci	for (int x = 1; x < width - 1; ++x)
3638e5c31af7Sopenharmony_ci	{
3639e5c31af7Sopenharmony_ci		const tcu::RGBA	refPixel			= reference.getPixel(x, y);
3640e5c31af7Sopenharmony_ci		const tcu::RGBA	screenPixel			= result.getPixel(x, y);
3641e5c31af7Sopenharmony_ci		const bool		directMatch			= colorsEqual(refPixel, screenPixel, compareThreshold);
3642e5c31af7Sopenharmony_ci		const bool		isOkScreenPixel		= directMatch || pixelNeighborhoodContainsColor(reference, x, y, screenPixel, compareThreshold);	// reference image has a matching pixel nearby (~= If something is drawn on screen, it must be drawn to reference too.)
3643e5c31af7Sopenharmony_ci		const bool		isOkReferencePixel	= directMatch || pixelNeighborhoodContainsColor(result, x, y, refPixel, compareThreshold);			// screen image has a matching pixel nearby (~= If something is drawn on reference, it must be drawn to screen too.)
3644e5c31af7Sopenharmony_ci
3645e5c31af7Sopenharmony_ci		if (isOkScreenPixel && isOkReferencePixel)
3646e5c31af7Sopenharmony_ci		{
3647e5c31af7Sopenharmony_ci			// pixel valid, write greenish pixels to make the result image easier to read
3648e5c31af7Sopenharmony_ci			const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3649e5c31af7Sopenharmony_ci			errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3650e5c31af7Sopenharmony_ci		}
3651e5c31af7Sopenharmony_ci		else if (!pixelNearLineIntersection(x, y, reference) &&
3652e5c31af7Sopenharmony_ci				 !pixelNearLineIntersection(x, y, result))
3653e5c31af7Sopenharmony_ci		{
3654e5c31af7Sopenharmony_ci			// non-intersection pixel values must be within threshold of the reference values
3655e5c31af7Sopenharmony_ci			errorAccess.setPixel(red, x, y);
3656e5c31af7Sopenharmony_ci			++numFailingPixels;
3657e5c31af7Sopenharmony_ci		}
3658e5c31af7Sopenharmony_ci		else
3659e5c31af7Sopenharmony_ci		{
3660e5c31af7Sopenharmony_ci			// pixel is near a line intersection
3661e5c31af7Sopenharmony_ci			// we are on/near an edge, verify only coverage (coverage == not background colored)
3662e5c31af7Sopenharmony_ci			const bool	referenceCoverage		= !isBlack(refPixel);
3663e5c31af7Sopenharmony_ci			const bool	screenCoverage			= !isBlack(screenPixel);
3664e5c31af7Sopenharmony_ci			const bool	isOkScreenCoverage		= pixelNeighborhoodContainsCoverage(reference, x, y, screenCoverage);	// Check screen pixels against reference pixel
3665e5c31af7Sopenharmony_ci			const bool	isOkReferenceCoverage	= pixelNeighborhoodContainsCoverage(result, x, y, referenceCoverage);	// Check reference pixel against screen pixel
3666e5c31af7Sopenharmony_ci
3667e5c31af7Sopenharmony_ci			if (isOkScreenCoverage && isOkReferenceCoverage)
3668e5c31af7Sopenharmony_ci			{
3669e5c31af7Sopenharmony_ci				// pixel valid, write greenish pixels to make the result image easier to read
3670e5c31af7Sopenharmony_ci				const deUint32 grayscaleValue = getVisualizationGrayscaleColor(screenPixel);
3671e5c31af7Sopenharmony_ci				errorAccess.setPixel(tcu::UVec4(grayscaleValue, 255, grayscaleValue, 255), x, y);
3672e5c31af7Sopenharmony_ci			}
3673e5c31af7Sopenharmony_ci			else
3674e5c31af7Sopenharmony_ci			{
3675e5c31af7Sopenharmony_ci				// coverage does not match
3676e5c31af7Sopenharmony_ci				errorAccess.setPixel(red, x, y);
3677e5c31af7Sopenharmony_ci				++numFailingPixels;
3678e5c31af7Sopenharmony_ci			}
3679e5c31af7Sopenharmony_ci		}
3680e5c31af7Sopenharmony_ci	}
3681e5c31af7Sopenharmony_ci
3682e5c31af7Sopenharmony_ci	log	<< TestLog::Message
3683e5c31af7Sopenharmony_ci		<< "Comparing images:\n"
3684e5c31af7Sopenharmony_ci		<< "\tallowed deviation in pixel positions = 1\n"
3685e5c31af7Sopenharmony_ci		<< "\tnumber of allowed invalid pixels = " << maxAllowedInvalidPixels << "\n"
3686e5c31af7Sopenharmony_ci		<< "\tnumber of invalid pixels = " << numFailingPixels
3687e5c31af7Sopenharmony_ci		<< TestLog::EndMessage;
3688e5c31af7Sopenharmony_ci
3689e5c31af7Sopenharmony_ci	if (numFailingPixels > maxAllowedInvalidPixels)
3690e5c31af7Sopenharmony_ci	{
3691e5c31af7Sopenharmony_ci		log << TestLog::Message
3692e5c31af7Sopenharmony_ci			<< "Image comparison failed. Color threshold = (" << compareThreshold.x() << ", " << compareThreshold.y() << ", " << compareThreshold.z() << ")"
3693e5c31af7Sopenharmony_ci			<< TestLog::EndMessage
3694e5c31af7Sopenharmony_ci			<< TestLog::ImageSet(imageSetName, imageSetDesc)
3695e5c31af7Sopenharmony_ci			<< TestLog::Image("Result",		"Result",		result)
3696e5c31af7Sopenharmony_ci			<< TestLog::Image("Reference",	"Reference",	reference)
3697e5c31af7Sopenharmony_ci			<< TestLog::Image("ErrorMask",	"Error mask",	errorMask)
3698e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
3699e5c31af7Sopenharmony_ci
3700e5c31af7Sopenharmony_ci		return false;
3701e5c31af7Sopenharmony_ci	}
3702e5c31af7Sopenharmony_ci	else
3703e5c31af7Sopenharmony_ci	{
3704e5c31af7Sopenharmony_ci		log << TestLog::ImageSet(imageSetName, imageSetDesc)
3705e5c31af7Sopenharmony_ci			<< TestLog::Image("Result", "Result", result)
3706e5c31af7Sopenharmony_ci			<< TestLog::EndImageSet;
3707e5c31af7Sopenharmony_ci
3708e5c31af7Sopenharmony_ci		return true;
3709e5c31af7Sopenharmony_ci	}
3710e5c31af7Sopenharmony_ci}
3711e5c31af7Sopenharmony_ci
3712e5c31af7Sopenharmony_cibool DrawTest::compare (gls::DrawTestSpec::Primitive primitiveType)
3713e5c31af7Sopenharmony_ci{
3714e5c31af7Sopenharmony_ci	const tcu::Surface&	ref		= m_rrArrayPack->getSurface();
3715e5c31af7Sopenharmony_ci	const tcu::Surface&	screen	= m_glArrayPack->getSurface();
3716e5c31af7Sopenharmony_ci
3717e5c31af7Sopenharmony_ci	if (m_renderCtx.getRenderTarget().getNumSamples() > 1)
3718e5c31af7Sopenharmony_ci	{
3719e5c31af7Sopenharmony_ci		// \todo [mika] Improve compare when using multisampling
3720e5c31af7Sopenharmony_ci		m_testCtx.getLog() << tcu::TestLog::Message << "Warning: Comparision of result from multisample render targets are not as stricts as without multisampling. Might produce false positives!" << tcu::TestLog::EndMessage;
3721e5c31af7Sopenharmony_ci		return tcu::fuzzyCompare(m_testCtx.getLog(), "Compare Results", "Compare Results", ref.getAccess(), screen.getAccess(), 0.3f, tcu::COMPARE_LOG_RESULT);
3722e5c31af7Sopenharmony_ci	}
3723e5c31af7Sopenharmony_ci	else
3724e5c31af7Sopenharmony_ci	{
3725e5c31af7Sopenharmony_ci		const PrimitiveClass	primitiveClass							= getDrawPrimitiveClass(primitiveType);
3726e5c31af7Sopenharmony_ci		const int				maxAllowedInvalidPixelsWithPoints		= 0;	//!< points are unlikely to have overlapping fragments
3727e5c31af7Sopenharmony_ci		const int				maxAllowedInvalidPixelsWithLines		= 5;	//!< line are allowed to have a few bad pixels
3728e5c31af7Sopenharmony_ci		const int				maxAllowedInvalidPixelsWithTriangles	= 10;
3729e5c31af7Sopenharmony_ci
3730e5c31af7Sopenharmony_ci		switch (primitiveClass)
3731e5c31af7Sopenharmony_ci		{
3732e5c31af7Sopenharmony_ci			case PRIMITIVECLASS_POINT:
3733e5c31af7Sopenharmony_ci			{
3734e5c31af7Sopenharmony_ci				// Point are extremely unlikely to have overlapping regions, don't allow any no extra / missing pixels
3735e5c31af7Sopenharmony_ci				return tcu::intThresholdPositionDeviationErrorThresholdCompare(m_testCtx.getLog(),
3736e5c31af7Sopenharmony_ci																			   "CompareResult",
3737e5c31af7Sopenharmony_ci																			   "Result of rendering",
3738e5c31af7Sopenharmony_ci																			   ref.getAccess(),
3739e5c31af7Sopenharmony_ci																			   screen.getAccess(),
3740e5c31af7Sopenharmony_ci																			   tcu::UVec4(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue, 256),
3741e5c31af7Sopenharmony_ci																			   tcu::IVec3(1, 1, 0),					//!< 3x3 search kernel
3742e5c31af7Sopenharmony_ci																			   true,								//!< relax comparison on the image boundary
3743e5c31af7Sopenharmony_ci																			   maxAllowedInvalidPixelsWithPoints,	//!< error threshold
3744e5c31af7Sopenharmony_ci																			   tcu::COMPARE_LOG_RESULT);
3745e5c31af7Sopenharmony_ci			}
3746e5c31af7Sopenharmony_ci
3747e5c31af7Sopenharmony_ci			case PRIMITIVECLASS_LINE:
3748e5c31af7Sopenharmony_ci			{
3749e5c31af7Sopenharmony_ci				// Lines can potentially have a large number of overlapping pixels. Pixel comparison may potentially produce
3750e5c31af7Sopenharmony_ci				// false negatives in such pixels if for example the pixel in question is overdrawn by another line in the
3751e5c31af7Sopenharmony_ci				// reference image but not in the resultin image. Relax comparison near line intersection points (areas) and
3752e5c31af7Sopenharmony_ci				// compare only coverage, not color, in such pixels
3753e5c31af7Sopenharmony_ci				return intersectionRelaxedLineImageCompare(m_testCtx.getLog(),
3754e5c31af7Sopenharmony_ci														   "CompareResult",
3755e5c31af7Sopenharmony_ci														   "Result of rendering",
3756e5c31af7Sopenharmony_ci														   ref,
3757e5c31af7Sopenharmony_ci														   screen,
3758e5c31af7Sopenharmony_ci														   tcu::IVec3(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue),
3759e5c31af7Sopenharmony_ci														   maxAllowedInvalidPixelsWithLines);
3760e5c31af7Sopenharmony_ci			}
3761e5c31af7Sopenharmony_ci
3762e5c31af7Sopenharmony_ci			case PRIMITIVECLASS_TRIANGLE:
3763e5c31af7Sopenharmony_ci			{
3764e5c31af7Sopenharmony_ci				// Triangles are likely to partially or fully overlap. Pixel difference comparison is fragile in pixels
3765e5c31af7Sopenharmony_ci				// where there could be potential overlapping since the  pixels might be covered by one triangle in the
3766e5c31af7Sopenharmony_ci				// reference image and by the other in the result image. Relax comparsion near primitive edges and
3767e5c31af7Sopenharmony_ci				// compare only coverage, not color, in such pixels.
3768e5c31af7Sopenharmony_ci				const tcu::IVec3	renderTargetThreshold					= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold().toIVec().xyz();
3769e5c31af7Sopenharmony_ci
3770e5c31af7Sopenharmony_ci				return edgeRelaxedImageCompare(m_testCtx.getLog(),
3771e5c31af7Sopenharmony_ci											   "CompareResult",
3772e5c31af7Sopenharmony_ci											   "Result of rendering",
3773e5c31af7Sopenharmony_ci											   ref,
3774e5c31af7Sopenharmony_ci											   screen,
3775e5c31af7Sopenharmony_ci											   tcu::IVec3(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue),
3776e5c31af7Sopenharmony_ci											   renderTargetThreshold,
3777e5c31af7Sopenharmony_ci											   maxAllowedInvalidPixelsWithTriangles);
3778e5c31af7Sopenharmony_ci			}
3779e5c31af7Sopenharmony_ci
3780e5c31af7Sopenharmony_ci			default:
3781e5c31af7Sopenharmony_ci				DE_ASSERT(false);
3782e5c31af7Sopenharmony_ci				return false;
3783e5c31af7Sopenharmony_ci		}
3784e5c31af7Sopenharmony_ci	}
3785e5c31af7Sopenharmony_ci}
3786e5c31af7Sopenharmony_ci
3787e5c31af7Sopenharmony_cifloat DrawTest::getCoordScale (const DrawTestSpec& spec) const
3788e5c31af7Sopenharmony_ci{
3789e5c31af7Sopenharmony_ci	float maxValue = 1.0f;
3790e5c31af7Sopenharmony_ci
3791e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)spec.attribs.size(); arrayNdx++)
3792e5c31af7Sopenharmony_ci	{
3793e5c31af7Sopenharmony_ci		DrawTestSpec::AttributeSpec attribSpec		= spec.attribs[arrayNdx];
3794e5c31af7Sopenharmony_ci		const bool					isPositionAttr	= (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
3795e5c31af7Sopenharmony_ci		float						attrMaxValue	= 0;
3796e5c31af7Sopenharmony_ci
3797e5c31af7Sopenharmony_ci		if (!isPositionAttr)
3798e5c31af7Sopenharmony_ci			continue;
3799e5c31af7Sopenharmony_ci
3800e5c31af7Sopenharmony_ci		if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
3801e5c31af7Sopenharmony_ci		{
3802e5c31af7Sopenharmony_ci			if (attribSpec.normalize)
3803e5c31af7Sopenharmony_ci				attrMaxValue += 1.0f;
3804e5c31af7Sopenharmony_ci			else
3805e5c31af7Sopenharmony_ci				attrMaxValue += 1024.0f;
3806e5c31af7Sopenharmony_ci		}
3807e5c31af7Sopenharmony_ci		else if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10)
3808e5c31af7Sopenharmony_ci		{
3809e5c31af7Sopenharmony_ci			if (attribSpec.normalize)
3810e5c31af7Sopenharmony_ci				attrMaxValue += 1.0f;
3811e5c31af7Sopenharmony_ci			else
3812e5c31af7Sopenharmony_ci				attrMaxValue += 512.0f;
3813e5c31af7Sopenharmony_ci		}
3814e5c31af7Sopenharmony_ci		else
3815e5c31af7Sopenharmony_ci		{
3816e5c31af7Sopenharmony_ci			const float max = GLValue::getMaxValue(attribSpec.inputType).toFloat();
3817e5c31af7Sopenharmony_ci
3818e5c31af7Sopenharmony_ci			attrMaxValue += (attribSpec.normalize && !inputTypeIsFloatType(attribSpec.inputType)) ? (1.0f) : (max * 1.1f);
3819e5c31af7Sopenharmony_ci		}
3820e5c31af7Sopenharmony_ci
3821e5c31af7Sopenharmony_ci		if (attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_VEC3 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_VEC4
3822e5c31af7Sopenharmony_ci			|| attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_IVEC3 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_IVEC4
3823e5c31af7Sopenharmony_ci			|| attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_UVEC3 || attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_UVEC4)
3824e5c31af7Sopenharmony_ci				attrMaxValue *= 2;
3825e5c31af7Sopenharmony_ci
3826e5c31af7Sopenharmony_ci		maxValue += attrMaxValue;
3827e5c31af7Sopenharmony_ci	}
3828e5c31af7Sopenharmony_ci
3829e5c31af7Sopenharmony_ci	return 1.0f / maxValue;
3830e5c31af7Sopenharmony_ci}
3831e5c31af7Sopenharmony_ci
3832e5c31af7Sopenharmony_cifloat DrawTest::getColorScale (const DrawTestSpec& spec) const
3833e5c31af7Sopenharmony_ci{
3834e5c31af7Sopenharmony_ci	float colorScale = 1.0f;
3835e5c31af7Sopenharmony_ci
3836e5c31af7Sopenharmony_ci	for (int arrayNdx = 1; arrayNdx < (int)spec.attribs.size(); arrayNdx++)
3837e5c31af7Sopenharmony_ci	{
3838e5c31af7Sopenharmony_ci		DrawTestSpec::AttributeSpec attribSpec		= spec.attribs[arrayNdx];
3839e5c31af7Sopenharmony_ci		const bool					isPositionAttr	= (arrayNdx == 0) || (attribSpec.additionalPositionAttribute);
3840e5c31af7Sopenharmony_ci
3841e5c31af7Sopenharmony_ci		if (isPositionAttr)
3842e5c31af7Sopenharmony_ci			continue;
3843e5c31af7Sopenharmony_ci
3844e5c31af7Sopenharmony_ci		if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
3845e5c31af7Sopenharmony_ci		{
3846e5c31af7Sopenharmony_ci			if (!attribSpec.normalize)
3847e5c31af7Sopenharmony_ci				colorScale *= 1.0f / 1024.0f;
3848e5c31af7Sopenharmony_ci		}
3849e5c31af7Sopenharmony_ci		else if (attribSpec.inputType == DrawTestSpec::INPUTTYPE_INT_2_10_10_10)
3850e5c31af7Sopenharmony_ci		{
3851e5c31af7Sopenharmony_ci			if (!attribSpec.normalize)
3852e5c31af7Sopenharmony_ci				colorScale *= 1.0f / 512.0f;
3853e5c31af7Sopenharmony_ci		}
3854e5c31af7Sopenharmony_ci		else
3855e5c31af7Sopenharmony_ci		{
3856e5c31af7Sopenharmony_ci			const float max = GLValue::getMaxValue(attribSpec.inputType).toFloat();
3857e5c31af7Sopenharmony_ci
3858e5c31af7Sopenharmony_ci			colorScale *= (attribSpec.normalize && !inputTypeIsFloatType(attribSpec.inputType) ? 1.0f : float(1.0 / double(max)));
3859e5c31af7Sopenharmony_ci			if (attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_VEC4 ||
3860e5c31af7Sopenharmony_ci				attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_UVEC4 ||
3861e5c31af7Sopenharmony_ci				attribSpec.outputType == DrawTestSpec::OUTPUTTYPE_IVEC4)
3862e5c31af7Sopenharmony_ci				colorScale *= (attribSpec.normalize && !inputTypeIsFloatType(attribSpec.inputType) ? 1.0f : float(1.0 / double(max)));
3863e5c31af7Sopenharmony_ci		}
3864e5c31af7Sopenharmony_ci	}
3865e5c31af7Sopenharmony_ci
3866e5c31af7Sopenharmony_ci	return colorScale;
3867e5c31af7Sopenharmony_ci}
3868e5c31af7Sopenharmony_ci
3869e5c31af7Sopenharmony_ci} // gls
3870e5c31af7Sopenharmony_ci} // deqp
3871