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 Vertex array and buffer tests
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "glsVertexArrayTests.hpp"
25e5c31af7Sopenharmony_ci
26e5c31af7Sopenharmony_ci#include "deRandom.h"
27e5c31af7Sopenharmony_ci
28e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
29e5c31af7Sopenharmony_ci#include "tcuPixelFormat.hpp"
30e5c31af7Sopenharmony_ci#include "tcuRGBA.hpp"
31e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
32e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
33e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
34e5c31af7Sopenharmony_ci#include "tcuRenderTarget.hpp"
35e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
36e5c31af7Sopenharmony_ci#include "tcuImageCompare.hpp"
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
39e5c31af7Sopenharmony_ci#include "gluCallLogWrapper.hpp"
40e5c31af7Sopenharmony_ci
41e5c31af7Sopenharmony_ci#include "sglrContext.hpp"
42e5c31af7Sopenharmony_ci#include "sglrReferenceContext.hpp"
43e5c31af7Sopenharmony_ci#include "sglrGLContext.hpp"
44e5c31af7Sopenharmony_ci
45e5c31af7Sopenharmony_ci#include "deMath.h"
46e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
47e5c31af7Sopenharmony_ci#include "deArrayUtil.hpp"
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_ci#include <cstring>
50e5c31af7Sopenharmony_ci#include <cmath>
51e5c31af7Sopenharmony_ci#include <vector>
52e5c31af7Sopenharmony_ci#include <sstream>
53e5c31af7Sopenharmony_ci#include <limits>
54e5c31af7Sopenharmony_ci#include <algorithm>
55e5c31af7Sopenharmony_ci
56e5c31af7Sopenharmony_ci#include "glwDefs.hpp"
57e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_cinamespace deqp
60e5c31af7Sopenharmony_ci{
61e5c31af7Sopenharmony_cinamespace gls
62e5c31af7Sopenharmony_ci{
63e5c31af7Sopenharmony_ci
64e5c31af7Sopenharmony_ciusing tcu::TestLog;
65e5c31af7Sopenharmony_ciusing namespace glw; // GL types
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_cistd::string Array::targetToString(Target target)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	static const char* targets[] =
70e5c31af7Sopenharmony_ci	{
71e5c31af7Sopenharmony_ci		"element_array",	// TARGET_ELEMENT_ARRAY = 0,
72e5c31af7Sopenharmony_ci		"array"				// TARGET_ARRAY,
73e5c31af7Sopenharmony_ci	};
74e5c31af7Sopenharmony_ci
75e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::TARGET_LAST>(targets, (int)target);
76e5c31af7Sopenharmony_ci}
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_cistd::string Array::inputTypeToString(InputType type)
79e5c31af7Sopenharmony_ci{
80e5c31af7Sopenharmony_ci	static const char* types[] =
81e5c31af7Sopenharmony_ci	{
82e5c31af7Sopenharmony_ci		"float",			// INPUTTYPE_FLOAT = 0,
83e5c31af7Sopenharmony_ci		"fixed",			// INPUTTYPE_FIXED,
84e5c31af7Sopenharmony_ci		"double",			// INPUTTYPE_DOUBLE
85e5c31af7Sopenharmony_ci
86e5c31af7Sopenharmony_ci		"byte",				// INPUTTYPE_BYTE,
87e5c31af7Sopenharmony_ci		"short",			// INPUTTYPE_SHORT,
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ci		"unsigned_byte",	// INPUTTYPE_UNSIGNED_BYTE,
90e5c31af7Sopenharmony_ci		"unsigned_short",	// INPUTTYPE_UNSIGNED_SHORT,
91e5c31af7Sopenharmony_ci
92e5c31af7Sopenharmony_ci		"int",						// INPUTTYPE_INT,
93e5c31af7Sopenharmony_ci		"unsigned_int",				// INPUTTYPE_UNSIGNED_INT,
94e5c31af7Sopenharmony_ci		"half",						// INPUTTYPE_HALF,
95e5c31af7Sopenharmony_ci		"usigned_int2_10_10_10",	// INPUTTYPE_UNSIGNED_INT_2_10_10_10,
96e5c31af7Sopenharmony_ci		"int2_10_10_10"				// INPUTTYPE_INT_2_10_10_10,
97e5c31af7Sopenharmony_ci	};
98e5c31af7Sopenharmony_ci
99e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::INPUTTYPE_LAST>(types, (int)type);
100e5c31af7Sopenharmony_ci}
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_cistd::string Array::outputTypeToString(OutputType type)
103e5c31af7Sopenharmony_ci{
104e5c31af7Sopenharmony_ci	static const char* types[] =
105e5c31af7Sopenharmony_ci	{
106e5c31af7Sopenharmony_ci		"float",		// OUTPUTTYPE_FLOAT = 0,
107e5c31af7Sopenharmony_ci		"vec2",			// OUTPUTTYPE_VEC2,
108e5c31af7Sopenharmony_ci		"vec3",			// OUTPUTTYPE_VEC3,
109e5c31af7Sopenharmony_ci		"vec4",			// OUTPUTTYPE_VEC4,
110e5c31af7Sopenharmony_ci
111e5c31af7Sopenharmony_ci		"int",			// OUTPUTTYPE_INT,
112e5c31af7Sopenharmony_ci		"uint",			// OUTPUTTYPE_UINT,
113e5c31af7Sopenharmony_ci
114e5c31af7Sopenharmony_ci		"ivec2",		// OUTPUTTYPE_IVEC2,
115e5c31af7Sopenharmony_ci		"ivec3",		// OUTPUTTYPE_IVEC3,
116e5c31af7Sopenharmony_ci		"ivec4",		// OUTPUTTYPE_IVEC4,
117e5c31af7Sopenharmony_ci
118e5c31af7Sopenharmony_ci		"uvec2",		// OUTPUTTYPE_UVEC2,
119e5c31af7Sopenharmony_ci		"uvec3",		// OUTPUTTYPE_UVEC3,
120e5c31af7Sopenharmony_ci		"uvec4",		// OUTPUTTYPE_UVEC4,
121e5c31af7Sopenharmony_ci	};
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::OUTPUTTYPE_LAST>(types, (int)type);
124e5c31af7Sopenharmony_ci}
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_cistd::string Array::usageTypeToString(Usage usage)
127e5c31af7Sopenharmony_ci{
128e5c31af7Sopenharmony_ci	static const char* usages[] =
129e5c31af7Sopenharmony_ci	{
130e5c31af7Sopenharmony_ci		"dynamic_draw",	// USAGE_DYNAMIC_DRAW = 0,
131e5c31af7Sopenharmony_ci		"static_draw",	// USAGE_STATIC_DRAW,
132e5c31af7Sopenharmony_ci		"stream_draw",	// USAGE_STREAM_DRAW,
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci		"stream_read",	// USAGE_STREAM_READ,
135e5c31af7Sopenharmony_ci		"stream_copy",	// USAGE_STREAM_COPY,
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ci		"static_read",	// USAGE_STATIC_READ,
138e5c31af7Sopenharmony_ci		"static_copy",	// USAGE_STATIC_COPY,
139e5c31af7Sopenharmony_ci
140e5c31af7Sopenharmony_ci		"dynamic_read",	// USAGE_DYNAMIC_READ,
141e5c31af7Sopenharmony_ci		"dynamic_copy",	// USAGE_DYNAMIC_COPY,
142e5c31af7Sopenharmony_ci	};
143e5c31af7Sopenharmony_ci
144e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::USAGE_LAST>(usages, (int)usage);
145e5c31af7Sopenharmony_ci}
146e5c31af7Sopenharmony_ci
147e5c31af7Sopenharmony_cistd::string	Array::storageToString (Storage storage)
148e5c31af7Sopenharmony_ci{
149e5c31af7Sopenharmony_ci	static const char* storages[] =
150e5c31af7Sopenharmony_ci	{
151e5c31af7Sopenharmony_ci		"user_ptr",	// STORAGE_USER = 0,
152e5c31af7Sopenharmony_ci		"buffer"	// STORAGE_BUFFER,
153e5c31af7Sopenharmony_ci	};
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::STORAGE_LAST>(storages, (int)storage);
156e5c31af7Sopenharmony_ci}
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_cistd::string Array::primitiveToString (Primitive primitive)
159e5c31af7Sopenharmony_ci{
160e5c31af7Sopenharmony_ci	static const char* primitives[] =
161e5c31af7Sopenharmony_ci	{
162e5c31af7Sopenharmony_ci		"points",			// PRIMITIVE_POINTS ,
163e5c31af7Sopenharmony_ci		"triangles",		// PRIMITIVE_TRIANGLES,
164e5c31af7Sopenharmony_ci		"triangle_fan",		// PRIMITIVE_TRIANGLE_FAN,
165e5c31af7Sopenharmony_ci		"triangle_strip"	// PRIMITIVE_TRIANGLE_STRIP,
166e5c31af7Sopenharmony_ci	};
167e5c31af7Sopenharmony_ci
168e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::PRIMITIVE_LAST>(primitives, (int)primitive);
169e5c31af7Sopenharmony_ci}
170e5c31af7Sopenharmony_ci
171e5c31af7Sopenharmony_ciint Array::inputTypeSize (InputType type)
172e5c31af7Sopenharmony_ci{
173e5c31af7Sopenharmony_ci	static const int size[] =
174e5c31af7Sopenharmony_ci	{
175e5c31af7Sopenharmony_ci		(int)sizeof(float),			// INPUTTYPE_FLOAT = 0,
176e5c31af7Sopenharmony_ci		(int)sizeof(deInt32),		// INPUTTYPE_FIXED,
177e5c31af7Sopenharmony_ci		(int)sizeof(double),		// INPUTTYPE_DOUBLE
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_ci		(int)sizeof(deInt8),		// INPUTTYPE_BYTE,
180e5c31af7Sopenharmony_ci		(int)sizeof(deInt16),		// INPUTTYPE_SHORT,
181e5c31af7Sopenharmony_ci
182e5c31af7Sopenharmony_ci		(int)sizeof(deUint8),		// INPUTTYPE_UNSIGNED_BYTE,
183e5c31af7Sopenharmony_ci		(int)sizeof(deUint16),		// INPUTTYPE_UNSIGNED_SHORT,
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ci		(int)sizeof(deInt32),		// INPUTTYPE_INT,
186e5c31af7Sopenharmony_ci		(int)sizeof(deUint32),		// INPUTTYPE_UNSIGNED_INT,
187e5c31af7Sopenharmony_ci		(int)sizeof(deFloat16),		// INPUTTYPE_HALF,
188e5c31af7Sopenharmony_ci		(int)sizeof(deUint32) / 4,	// INPUTTYPE_UNSIGNED_INT_2_10_10_10,
189e5c31af7Sopenharmony_ci		(int)sizeof(deUint32) / 4	// INPUTTYPE_INT_2_10_10_10,
190e5c31af7Sopenharmony_ci	};
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::INPUTTYPE_LAST>(size, (int)type);
193e5c31af7Sopenharmony_ci}
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_cistatic bool inputTypeIsFloatType (Array::InputType type)
196e5c31af7Sopenharmony_ci{
197e5c31af7Sopenharmony_ci	if (type == Array::INPUTTYPE_FLOAT)
198e5c31af7Sopenharmony_ci		return true;
199e5c31af7Sopenharmony_ci	if (type == Array::INPUTTYPE_FIXED)
200e5c31af7Sopenharmony_ci		return true;
201e5c31af7Sopenharmony_ci	if (type == Array::INPUTTYPE_DOUBLE)
202e5c31af7Sopenharmony_ci		return true;
203e5c31af7Sopenharmony_ci	if (type == Array::INPUTTYPE_HALF)
204e5c31af7Sopenharmony_ci		return true;
205e5c31af7Sopenharmony_ci	return false;
206e5c31af7Sopenharmony_ci}
207e5c31af7Sopenharmony_ci
208e5c31af7Sopenharmony_cistatic bool outputTypeIsFloatType (Array::OutputType type)
209e5c31af7Sopenharmony_ci{
210e5c31af7Sopenharmony_ci	if (type == Array::OUTPUTTYPE_FLOAT
211e5c31af7Sopenharmony_ci		|| type == Array::OUTPUTTYPE_VEC2
212e5c31af7Sopenharmony_ci		|| type == Array::OUTPUTTYPE_VEC3
213e5c31af7Sopenharmony_ci		|| type == Array::OUTPUTTYPE_VEC4)
214e5c31af7Sopenharmony_ci		return true;
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ci	return false;
217e5c31af7Sopenharmony_ci}
218e5c31af7Sopenharmony_ci
219e5c31af7Sopenharmony_citemplate<class T>
220e5c31af7Sopenharmony_ciinline T getRandom (deRandom& rnd, T min, T max);
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_citemplate<>
223e5c31af7Sopenharmony_ciinline GLValue::Float getRandom (deRandom& rnd, GLValue::Float min, GLValue::Float max)
224e5c31af7Sopenharmony_ci{
225e5c31af7Sopenharmony_ci	if (max < min)
226e5c31af7Sopenharmony_ci		return min;
227e5c31af7Sopenharmony_ci
228e5c31af7Sopenharmony_ci	return GLValue::Float::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
229e5c31af7Sopenharmony_ci}
230e5c31af7Sopenharmony_ci
231e5c31af7Sopenharmony_citemplate<>
232e5c31af7Sopenharmony_ciinline GLValue::Short getRandom (deRandom& rnd, GLValue::Short min, GLValue::Short max)
233e5c31af7Sopenharmony_ci{
234e5c31af7Sopenharmony_ci	if (max < min)
235e5c31af7Sopenharmony_ci		return min;
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci	return GLValue::Short::create((min == max ? min : (deInt16)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
238e5c31af7Sopenharmony_ci}
239e5c31af7Sopenharmony_ci
240e5c31af7Sopenharmony_citemplate<>
241e5c31af7Sopenharmony_ciinline GLValue::Ushort getRandom (deRandom& rnd, GLValue::Ushort min, GLValue::Ushort max)
242e5c31af7Sopenharmony_ci{
243e5c31af7Sopenharmony_ci	if (max < min)
244e5c31af7Sopenharmony_ci		return min;
245e5c31af7Sopenharmony_ci
246e5c31af7Sopenharmony_ci	return GLValue::Ushort::create((min == max ? min : (deUint16)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
247e5c31af7Sopenharmony_ci}
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_citemplate<>
250e5c31af7Sopenharmony_ciinline GLValue::Byte getRandom (deRandom& rnd, GLValue::Byte min, GLValue::Byte max)
251e5c31af7Sopenharmony_ci{
252e5c31af7Sopenharmony_ci	if (max < min)
253e5c31af7Sopenharmony_ci		return min;
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ci	return GLValue::Byte::create((min == max ? min : (deInt8)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
256e5c31af7Sopenharmony_ci}
257e5c31af7Sopenharmony_ci
258e5c31af7Sopenharmony_citemplate<>
259e5c31af7Sopenharmony_ciinline GLValue::Ubyte getRandom (deRandom& rnd, GLValue::Ubyte min, GLValue::Ubyte max)
260e5c31af7Sopenharmony_ci{
261e5c31af7Sopenharmony_ci	if (max < min)
262e5c31af7Sopenharmony_ci		return min;
263e5c31af7Sopenharmony_ci
264e5c31af7Sopenharmony_ci	return GLValue::Ubyte::create((min == max ? min : (deUint8)(min + (deRandom_getUint32(&rnd) % (max.to<int>() - min.to<int>())))));
265e5c31af7Sopenharmony_ci}
266e5c31af7Sopenharmony_ci
267e5c31af7Sopenharmony_citemplate<>
268e5c31af7Sopenharmony_ciinline GLValue::Fixed getRandom (deRandom& rnd, GLValue::Fixed min, GLValue::Fixed max)
269e5c31af7Sopenharmony_ci{
270e5c31af7Sopenharmony_ci	if (max < min)
271e5c31af7Sopenharmony_ci		return min;
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci	return GLValue::Fixed::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
274e5c31af7Sopenharmony_ci}
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_citemplate<>
277e5c31af7Sopenharmony_ciinline GLValue::Half getRandom (deRandom& rnd, GLValue::Half min, GLValue::Half max)
278e5c31af7Sopenharmony_ci{
279e5c31af7Sopenharmony_ci	if (max < min)
280e5c31af7Sopenharmony_ci		return min;
281e5c31af7Sopenharmony_ci
282e5c31af7Sopenharmony_ci	float fMax = max.to<float>();
283e5c31af7Sopenharmony_ci	float fMin = min.to<float>();
284e5c31af7Sopenharmony_ci	GLValue::Half h = GLValue::Half::create(fMin + deRandom_getFloat(&rnd) * (fMax - fMin));
285e5c31af7Sopenharmony_ci	return h;
286e5c31af7Sopenharmony_ci}
287e5c31af7Sopenharmony_ci
288e5c31af7Sopenharmony_citemplate<>
289e5c31af7Sopenharmony_ciinline GLValue::Int getRandom (deRandom& rnd, GLValue::Int min, GLValue::Int max)
290e5c31af7Sopenharmony_ci{
291e5c31af7Sopenharmony_ci	if (max < min)
292e5c31af7Sopenharmony_ci		return min;
293e5c31af7Sopenharmony_ci
294e5c31af7Sopenharmony_ci	return GLValue::Int::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
295e5c31af7Sopenharmony_ci}
296e5c31af7Sopenharmony_ci
297e5c31af7Sopenharmony_citemplate<>
298e5c31af7Sopenharmony_ciinline GLValue::Uint getRandom (deRandom& rnd, GLValue::Uint min, GLValue::Uint max)
299e5c31af7Sopenharmony_ci{
300e5c31af7Sopenharmony_ci	if (max < min)
301e5c31af7Sopenharmony_ci		return min;
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci	return GLValue::Uint::create((min == max ? min : min + (deRandom_getUint32(&rnd) % (max.to<deUint32>() - min.to<deUint32>()))));
304e5c31af7Sopenharmony_ci}
305e5c31af7Sopenharmony_ci
306e5c31af7Sopenharmony_citemplate<>
307e5c31af7Sopenharmony_ciinline GLValue::Double getRandom (deRandom& rnd, GLValue::Double min, GLValue::Double max)
308e5c31af7Sopenharmony_ci{
309e5c31af7Sopenharmony_ci	if (max < min)
310e5c31af7Sopenharmony_ci		return min;
311e5c31af7Sopenharmony_ci
312e5c31af7Sopenharmony_ci	return GLValue::Double::create(min + deRandom_getFloat(&rnd) * (max.to<float>() - min.to<float>()));
313e5c31af7Sopenharmony_ci}
314e5c31af7Sopenharmony_ci
315e5c31af7Sopenharmony_ci// Minimum difference required between coordinates
316e5c31af7Sopenharmony_citemplate<class T>
317e5c31af7Sopenharmony_ciinline T minValue (void);
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_citemplate<>
320e5c31af7Sopenharmony_ciinline GLValue::Float minValue (void)
321e5c31af7Sopenharmony_ci{
322e5c31af7Sopenharmony_ci	return GLValue::Float::create(4 * 1.0f);
323e5c31af7Sopenharmony_ci}
324e5c31af7Sopenharmony_ci
325e5c31af7Sopenharmony_citemplate<>
326e5c31af7Sopenharmony_ciinline GLValue::Short minValue (void)
327e5c31af7Sopenharmony_ci{
328e5c31af7Sopenharmony_ci	return GLValue::Short::create(4 * 256);
329e5c31af7Sopenharmony_ci}
330e5c31af7Sopenharmony_ci
331e5c31af7Sopenharmony_citemplate<>
332e5c31af7Sopenharmony_ciinline GLValue::Ushort minValue (void)
333e5c31af7Sopenharmony_ci{
334e5c31af7Sopenharmony_ci	return GLValue::Ushort::create(4 * 256);
335e5c31af7Sopenharmony_ci}
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_citemplate<>
338e5c31af7Sopenharmony_ciinline GLValue::Byte minValue (void)
339e5c31af7Sopenharmony_ci{
340e5c31af7Sopenharmony_ci	return GLValue::Byte::create(4 * 1);
341e5c31af7Sopenharmony_ci}
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_citemplate<>
344e5c31af7Sopenharmony_ciinline GLValue::Ubyte minValue (void)
345e5c31af7Sopenharmony_ci{
346e5c31af7Sopenharmony_ci	return GLValue::Ubyte::create(4 * 2);
347e5c31af7Sopenharmony_ci}
348e5c31af7Sopenharmony_ci
349e5c31af7Sopenharmony_citemplate<>
350e5c31af7Sopenharmony_ciinline GLValue::Fixed minValue (void)
351e5c31af7Sopenharmony_ci{
352e5c31af7Sopenharmony_ci	return GLValue::Fixed::create(4 * 512);
353e5c31af7Sopenharmony_ci}
354e5c31af7Sopenharmony_ci
355e5c31af7Sopenharmony_citemplate<>
356e5c31af7Sopenharmony_ciinline GLValue::Int minValue (void)
357e5c31af7Sopenharmony_ci{
358e5c31af7Sopenharmony_ci	return GLValue::Int::create(4 * 16777216);
359e5c31af7Sopenharmony_ci}
360e5c31af7Sopenharmony_ci
361e5c31af7Sopenharmony_citemplate<>
362e5c31af7Sopenharmony_ciinline GLValue::Uint minValue (void)
363e5c31af7Sopenharmony_ci{
364e5c31af7Sopenharmony_ci	return GLValue::Uint::create(4 * 16777216);
365e5c31af7Sopenharmony_ci}
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_citemplate<>
368e5c31af7Sopenharmony_ciinline GLValue::Half minValue (void)
369e5c31af7Sopenharmony_ci{
370e5c31af7Sopenharmony_ci	return GLValue::Half::create(4 * 1.0f);
371e5c31af7Sopenharmony_ci}
372e5c31af7Sopenharmony_ci
373e5c31af7Sopenharmony_citemplate<>
374e5c31af7Sopenharmony_ciinline GLValue::Double minValue (void)
375e5c31af7Sopenharmony_ci{
376e5c31af7Sopenharmony_ci	return GLValue::Double::create(4 * 1.0f);
377e5c31af7Sopenharmony_ci}
378e5c31af7Sopenharmony_ci
379e5c31af7Sopenharmony_citemplate<class T>
380e5c31af7Sopenharmony_cistatic inline void alignmentSafeAssignment (char* dst, T val)
381e5c31af7Sopenharmony_ci{
382e5c31af7Sopenharmony_ci	std::memcpy(dst, &val, sizeof(T));
383e5c31af7Sopenharmony_ci}
384e5c31af7Sopenharmony_ci
385e5c31af7Sopenharmony_ciContextArray::ContextArray (Storage storage, sglr::Context& context)
386e5c31af7Sopenharmony_ci	: m_storage			(storage)
387e5c31af7Sopenharmony_ci	, m_ctx				(context)
388e5c31af7Sopenharmony_ci	, m_glBuffer		(0)
389e5c31af7Sopenharmony_ci	, m_bound			(false)
390e5c31af7Sopenharmony_ci	, m_attribNdx		(0)
391e5c31af7Sopenharmony_ci	, m_size			(0)
392e5c31af7Sopenharmony_ci	, m_data			(DE_NULL)
393e5c31af7Sopenharmony_ci	, m_componentCount	(1)
394e5c31af7Sopenharmony_ci	, m_target			(Array::TARGET_ARRAY)
395e5c31af7Sopenharmony_ci	, m_inputType		(Array::INPUTTYPE_FLOAT)
396e5c31af7Sopenharmony_ci	, m_outputType		(Array::OUTPUTTYPE_VEC4)
397e5c31af7Sopenharmony_ci	, m_normalize		(false)
398e5c31af7Sopenharmony_ci	, m_stride			(0)
399e5c31af7Sopenharmony_ci	, m_offset			(0)
400e5c31af7Sopenharmony_ci{
401e5c31af7Sopenharmony_ci	if (m_storage == STORAGE_BUFFER)
402e5c31af7Sopenharmony_ci	{
403e5c31af7Sopenharmony_ci		m_ctx.genBuffers(1, &m_glBuffer);
404e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glGenBuffers()");
405e5c31af7Sopenharmony_ci	}
406e5c31af7Sopenharmony_ci}
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_ciContextArray::~ContextArray	(void)
409e5c31af7Sopenharmony_ci{
410e5c31af7Sopenharmony_ci	if (m_storage == STORAGE_BUFFER)
411e5c31af7Sopenharmony_ci	{
412e5c31af7Sopenharmony_ci		m_ctx.deleteBuffers(1, &m_glBuffer);
413e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDeleteBuffers()");
414e5c31af7Sopenharmony_ci	}
415e5c31af7Sopenharmony_ci	else if (m_storage == STORAGE_USER)
416e5c31af7Sopenharmony_ci		delete[] m_data;
417e5c31af7Sopenharmony_ci	else
418e5c31af7Sopenharmony_ci		DE_ASSERT(false);
419e5c31af7Sopenharmony_ci}
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ciArray* ContextArrayPack::getArray (int i)
422e5c31af7Sopenharmony_ci{
423e5c31af7Sopenharmony_ci	return m_arrays.at(i);
424e5c31af7Sopenharmony_ci}
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_civoid ContextArray::data (Target target, int size, const char* ptr, Usage usage)
427e5c31af7Sopenharmony_ci{
428e5c31af7Sopenharmony_ci	m_size = size;
429e5c31af7Sopenharmony_ci	m_target = target;
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci	if (m_storage == STORAGE_BUFFER)
432e5c31af7Sopenharmony_ci	{
433e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
434e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
435e5c31af7Sopenharmony_ci
436e5c31af7Sopenharmony_ci		m_ctx.bufferData(targetToGL(target), size, ptr, usageToGL(usage));
437e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferData()");
438e5c31af7Sopenharmony_ci	}
439e5c31af7Sopenharmony_ci	else if (m_storage == STORAGE_USER)
440e5c31af7Sopenharmony_ci	{
441e5c31af7Sopenharmony_ci		if (m_data)
442e5c31af7Sopenharmony_ci			delete[] m_data;
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_ci		m_data = new char[size];
445e5c31af7Sopenharmony_ci		std::memcpy(m_data, ptr, size);
446e5c31af7Sopenharmony_ci	}
447e5c31af7Sopenharmony_ci	else
448e5c31af7Sopenharmony_ci		DE_ASSERT(false);
449e5c31af7Sopenharmony_ci}
450e5c31af7Sopenharmony_ci
451e5c31af7Sopenharmony_civoid ContextArray::subdata (Target target, int offset, int size, const char* ptr)
452e5c31af7Sopenharmony_ci{
453e5c31af7Sopenharmony_ci	m_target = target;
454e5c31af7Sopenharmony_ci
455e5c31af7Sopenharmony_ci	if (m_storage == STORAGE_BUFFER)
456e5c31af7Sopenharmony_ci	{
457e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
458e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ci		m_ctx.bufferSubData(targetToGL(target), offset, size, ptr);
461e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBufferSubData()");
462e5c31af7Sopenharmony_ci	}
463e5c31af7Sopenharmony_ci	else if (m_storage == STORAGE_USER)
464e5c31af7Sopenharmony_ci		std::memcpy(m_data + offset, ptr, size);
465e5c31af7Sopenharmony_ci	else
466e5c31af7Sopenharmony_ci		DE_ASSERT(false);
467e5c31af7Sopenharmony_ci}
468e5c31af7Sopenharmony_ci
469e5c31af7Sopenharmony_civoid ContextArray::bind (int attribNdx, int offset, int size, InputType inputType, OutputType outType, bool normalized, int stride)
470e5c31af7Sopenharmony_ci{
471e5c31af7Sopenharmony_ci	m_attribNdx			= attribNdx;
472e5c31af7Sopenharmony_ci	m_bound				= true;
473e5c31af7Sopenharmony_ci	m_componentCount	= size;
474e5c31af7Sopenharmony_ci	m_inputType			= inputType;
475e5c31af7Sopenharmony_ci	m_outputType		= outType;
476e5c31af7Sopenharmony_ci	m_normalize			= normalized;
477e5c31af7Sopenharmony_ci	m_stride			= stride;
478e5c31af7Sopenharmony_ci	m_offset			= offset;
479e5c31af7Sopenharmony_ci}
480e5c31af7Sopenharmony_ci
481e5c31af7Sopenharmony_civoid ContextArray::bindIndexArray (Array::Target target)
482e5c31af7Sopenharmony_ci{
483e5c31af7Sopenharmony_ci	if (m_storage == STORAGE_USER)
484e5c31af7Sopenharmony_ci	{
485e5c31af7Sopenharmony_ci	}
486e5c31af7Sopenharmony_ci	else if (m_storage == STORAGE_BUFFER)
487e5c31af7Sopenharmony_ci	{
488e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(target), m_glBuffer);
489e5c31af7Sopenharmony_ci	}
490e5c31af7Sopenharmony_ci}
491e5c31af7Sopenharmony_ci
492e5c31af7Sopenharmony_civoid ContextArray::glBind (deUint32 loc)
493e5c31af7Sopenharmony_ci{
494e5c31af7Sopenharmony_ci	if (m_storage == STORAGE_BUFFER)
495e5c31af7Sopenharmony_ci	{
496e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(m_target), m_glBuffer);
497e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
498e5c31af7Sopenharmony_ci
499e5c31af7Sopenharmony_ci		if (!inputTypeIsFloatType(m_inputType))
500e5c31af7Sopenharmony_ci		{
501e5c31af7Sopenharmony_ci			// Input is not float type
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_ci			if (outputTypeIsFloatType(m_outputType))
504e5c31af7Sopenharmony_ci			{
505e5c31af7Sopenharmony_ci				// Output type is float type
506e5c31af7Sopenharmony_ci				m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, (GLvoid*)((GLintptr)m_offset));
507e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
508e5c31af7Sopenharmony_ci			}
509e5c31af7Sopenharmony_ci			else
510e5c31af7Sopenharmony_ci			{
511e5c31af7Sopenharmony_ci				// Output type is int type
512e5c31af7Sopenharmony_ci				m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, (GLvoid*)((GLintptr)m_offset));
513e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()");
514e5c31af7Sopenharmony_ci			}
515e5c31af7Sopenharmony_ci		}
516e5c31af7Sopenharmony_ci		else
517e5c31af7Sopenharmony_ci		{
518e5c31af7Sopenharmony_ci			// Input type is float type
519e5c31af7Sopenharmony_ci
520e5c31af7Sopenharmony_ci			// Output type must be float type
521e5c31af7Sopenharmony_ci			DE_ASSERT(m_outputType == OUTPUTTYPE_FLOAT || m_outputType == OUTPUTTYPE_VEC2 || m_outputType == OUTPUTTYPE_VEC3 || m_outputType == OUTPUTTYPE_VEC4);
522e5c31af7Sopenharmony_ci
523e5c31af7Sopenharmony_ci			m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, (GLvoid*)((GLintptr)m_offset));
524e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
525e5c31af7Sopenharmony_ci		}
526e5c31af7Sopenharmony_ci
527e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(m_target), 0);
528e5c31af7Sopenharmony_ci	}
529e5c31af7Sopenharmony_ci	else if (m_storage == STORAGE_USER)
530e5c31af7Sopenharmony_ci	{
531e5c31af7Sopenharmony_ci		m_ctx.bindBuffer(targetToGL(m_target), 0);
532e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glBindBuffer()");
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci		if (!inputTypeIsFloatType(m_inputType))
535e5c31af7Sopenharmony_ci		{
536e5c31af7Sopenharmony_ci			// Input is not float type
537e5c31af7Sopenharmony_ci
538e5c31af7Sopenharmony_ci			if (outputTypeIsFloatType(m_outputType))
539e5c31af7Sopenharmony_ci			{
540e5c31af7Sopenharmony_ci				// Output type is float type
541e5c31af7Sopenharmony_ci				m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, m_data + m_offset);
542e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
543e5c31af7Sopenharmony_ci			}
544e5c31af7Sopenharmony_ci			else
545e5c31af7Sopenharmony_ci			{
546e5c31af7Sopenharmony_ci				// Output type is int type
547e5c31af7Sopenharmony_ci				m_ctx.vertexAttribIPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_stride, m_data + m_offset);
548e5c31af7Sopenharmony_ci				GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribIPointer()");
549e5c31af7Sopenharmony_ci			}
550e5c31af7Sopenharmony_ci		}
551e5c31af7Sopenharmony_ci		else
552e5c31af7Sopenharmony_ci		{
553e5c31af7Sopenharmony_ci			// Input type is float type
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ci			// Output type must be float type
556e5c31af7Sopenharmony_ci			DE_ASSERT(m_outputType == OUTPUTTYPE_FLOAT || m_outputType == OUTPUTTYPE_VEC2 || m_outputType == OUTPUTTYPE_VEC3 || m_outputType == OUTPUTTYPE_VEC4);
557e5c31af7Sopenharmony_ci
558e5c31af7Sopenharmony_ci			m_ctx.vertexAttribPointer(loc, m_componentCount, inputTypeToGL(m_inputType), m_normalize, m_stride, m_data + m_offset);
559e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glVertexAttribPointer()");
560e5c31af7Sopenharmony_ci		}
561e5c31af7Sopenharmony_ci	}
562e5c31af7Sopenharmony_ci	else
563e5c31af7Sopenharmony_ci		DE_ASSERT(false);
564e5c31af7Sopenharmony_ci}
565e5c31af7Sopenharmony_ci
566e5c31af7Sopenharmony_ciGLenum ContextArray::targetToGL (Array::Target target)
567e5c31af7Sopenharmony_ci{
568e5c31af7Sopenharmony_ci	static const GLenum targets[] =
569e5c31af7Sopenharmony_ci	{
570e5c31af7Sopenharmony_ci		GL_ELEMENT_ARRAY_BUFFER,	// TARGET_ELEMENT_ARRAY = 0,
571e5c31af7Sopenharmony_ci		GL_ARRAY_BUFFER				// TARGET_ARRAY,
572e5c31af7Sopenharmony_ci	};
573e5c31af7Sopenharmony_ci
574e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::TARGET_LAST>(targets, (int)target);
575e5c31af7Sopenharmony_ci}
576e5c31af7Sopenharmony_ci
577e5c31af7Sopenharmony_ciGLenum ContextArray::usageToGL (Array::Usage usage)
578e5c31af7Sopenharmony_ci{
579e5c31af7Sopenharmony_ci	static const GLenum usages[] =
580e5c31af7Sopenharmony_ci	{
581e5c31af7Sopenharmony_ci		GL_DYNAMIC_DRAW,	// USAGE_DYNAMIC_DRAW = 0,
582e5c31af7Sopenharmony_ci		GL_STATIC_DRAW,		// USAGE_STATIC_DRAW,
583e5c31af7Sopenharmony_ci		GL_STREAM_DRAW,		// USAGE_STREAM_DRAW,
584e5c31af7Sopenharmony_ci
585e5c31af7Sopenharmony_ci		GL_STREAM_READ,		// USAGE_STREAM_READ,
586e5c31af7Sopenharmony_ci		GL_STREAM_COPY,		// USAGE_STREAM_COPY,
587e5c31af7Sopenharmony_ci
588e5c31af7Sopenharmony_ci		GL_STATIC_READ,		// USAGE_STATIC_READ,
589e5c31af7Sopenharmony_ci		GL_STATIC_COPY,		// USAGE_STATIC_COPY,
590e5c31af7Sopenharmony_ci
591e5c31af7Sopenharmony_ci		GL_DYNAMIC_READ,	// USAGE_DYNAMIC_READ,
592e5c31af7Sopenharmony_ci		GL_DYNAMIC_COPY		// USAGE_DYNAMIC_COPY,
593e5c31af7Sopenharmony_ci	};
594e5c31af7Sopenharmony_ci
595e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::USAGE_LAST>(usages, (int)usage);
596e5c31af7Sopenharmony_ci}
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ciGLenum ContextArray::inputTypeToGL (Array::InputType type)
599e5c31af7Sopenharmony_ci{
600e5c31af7Sopenharmony_ci	static const GLenum types[] =
601e5c31af7Sopenharmony_ci	{
602e5c31af7Sopenharmony_ci		GL_FLOAT,				// INPUTTYPE_FLOAT = 0,
603e5c31af7Sopenharmony_ci		GL_FIXED,				// INPUTTYPE_FIXED,
604e5c31af7Sopenharmony_ci		GL_DOUBLE,				// INPUTTYPE_DOUBLE
605e5c31af7Sopenharmony_ci		GL_BYTE,				// INPUTTYPE_BYTE,
606e5c31af7Sopenharmony_ci		GL_SHORT,				// INPUTTYPE_SHORT,
607e5c31af7Sopenharmony_ci		GL_UNSIGNED_BYTE,		// INPUTTYPE_UNSIGNED_BYTE,
608e5c31af7Sopenharmony_ci		GL_UNSIGNED_SHORT,		// INPUTTYPE_UNSIGNED_SHORT,
609e5c31af7Sopenharmony_ci
610e5c31af7Sopenharmony_ci		GL_INT,					// INPUTTYPE_INT,
611e5c31af7Sopenharmony_ci		GL_UNSIGNED_INT,		// INPUTTYPE_UNSIGNED_INT,
612e5c31af7Sopenharmony_ci		GL_HALF_FLOAT,			// INPUTTYPE_HALF,
613e5c31af7Sopenharmony_ci		GL_UNSIGNED_INT_2_10_10_10_REV, // INPUTTYPE_UNSIGNED_INT_2_10_10_10,
614e5c31af7Sopenharmony_ci		GL_INT_2_10_10_10_REV			// INPUTTYPE_INT_2_10_10_10,
615e5c31af7Sopenharmony_ci	};
616e5c31af7Sopenharmony_ci
617e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::INPUTTYPE_LAST>(types, (int)type);
618e5c31af7Sopenharmony_ci}
619e5c31af7Sopenharmony_ci
620e5c31af7Sopenharmony_cistd::string ContextArray::outputTypeToGLType (Array::OutputType type)
621e5c31af7Sopenharmony_ci{
622e5c31af7Sopenharmony_ci	static const char* types[] =
623e5c31af7Sopenharmony_ci	{
624e5c31af7Sopenharmony_ci		"float",		// OUTPUTTYPE_FLOAT = 0,
625e5c31af7Sopenharmony_ci		"vec2",			// OUTPUTTYPE_VEC2,
626e5c31af7Sopenharmony_ci		"vec3",			// OUTPUTTYPE_VEC3,
627e5c31af7Sopenharmony_ci		"vec4",			// OUTPUTTYPE_VEC4,
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_ci		"int",			// OUTPUTTYPE_INT,
630e5c31af7Sopenharmony_ci		"uint",			// OUTPUTTYPE_UINT,
631e5c31af7Sopenharmony_ci
632e5c31af7Sopenharmony_ci		"ivec2",		// OUTPUTTYPE_IVEC2,
633e5c31af7Sopenharmony_ci		"ivec3",		// OUTPUTTYPE_IVEC3,
634e5c31af7Sopenharmony_ci		"ivec4",		// OUTPUTTYPE_IVEC4,
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_ci		"uvec2",		// OUTPUTTYPE_UVEC2,
637e5c31af7Sopenharmony_ci		"uvec3",		// OUTPUTTYPE_UVEC3,
638e5c31af7Sopenharmony_ci		"uvec4",		// OUTPUTTYPE_UVEC4,
639e5c31af7Sopenharmony_ci	};
640e5c31af7Sopenharmony_ci
641e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::OUTPUTTYPE_LAST>(types, (int)type);
642e5c31af7Sopenharmony_ci}
643e5c31af7Sopenharmony_ci
644e5c31af7Sopenharmony_ciGLenum ContextArray::primitiveToGL (Array::Primitive primitive)
645e5c31af7Sopenharmony_ci{
646e5c31af7Sopenharmony_ci	static const GLenum primitives[] =
647e5c31af7Sopenharmony_ci	{
648e5c31af7Sopenharmony_ci		GL_POINTS,			// PRIMITIVE_POINTS = 0,
649e5c31af7Sopenharmony_ci		GL_TRIANGLES,		// PRIMITIVE_TRIANGLES,
650e5c31af7Sopenharmony_ci		GL_TRIANGLE_FAN,	// PRIMITIVE_TRIANGLE_FAN,
651e5c31af7Sopenharmony_ci		GL_TRIANGLE_STRIP	// PRIMITIVE_TRIANGLE_STRIP,
652e5c31af7Sopenharmony_ci	};
653e5c31af7Sopenharmony_ci
654e5c31af7Sopenharmony_ci	return de::getSizedArrayElement<Array::PRIMITIVE_LAST>(primitives, (int)primitive);
655e5c31af7Sopenharmony_ci}
656e5c31af7Sopenharmony_ci
657e5c31af7Sopenharmony_ciContextArrayPack::ContextArrayPack (glu::RenderContext& renderCtx, sglr::Context& drawContext)
658e5c31af7Sopenharmony_ci	: m_renderCtx	(renderCtx)
659e5c31af7Sopenharmony_ci	, m_ctx			(drawContext)
660e5c31af7Sopenharmony_ci	, m_program		(DE_NULL)
661e5c31af7Sopenharmony_ci	, m_screen		(std::min(512, renderCtx.getRenderTarget().getWidth()), std::min(512, renderCtx.getRenderTarget().getHeight()))
662e5c31af7Sopenharmony_ci{
663e5c31af7Sopenharmony_ci}
664e5c31af7Sopenharmony_ci
665e5c31af7Sopenharmony_ciContextArrayPack::~ContextArrayPack (void)
666e5c31af7Sopenharmony_ci{
667e5c31af7Sopenharmony_ci	for (std::vector<ContextArray*>::iterator itr = m_arrays.begin(); itr != m_arrays.end(); itr++)
668e5c31af7Sopenharmony_ci		delete *itr;
669e5c31af7Sopenharmony_ci
670e5c31af7Sopenharmony_ci	delete m_program;
671e5c31af7Sopenharmony_ci}
672e5c31af7Sopenharmony_ci
673e5c31af7Sopenharmony_ciint ContextArrayPack::getArrayCount (void)
674e5c31af7Sopenharmony_ci{
675e5c31af7Sopenharmony_ci	return (int)m_arrays.size();
676e5c31af7Sopenharmony_ci}
677e5c31af7Sopenharmony_ci
678e5c31af7Sopenharmony_civoid ContextArrayPack::newArray (Array::Storage storage)
679e5c31af7Sopenharmony_ci{
680e5c31af7Sopenharmony_ci	m_arrays.push_back(new ContextArray(storage, m_ctx));
681e5c31af7Sopenharmony_ci}
682e5c31af7Sopenharmony_ci
683e5c31af7Sopenharmony_ciclass ContextShaderProgram : public sglr::ShaderProgram
684e5c31af7Sopenharmony_ci{
685e5c31af7Sopenharmony_cipublic:
686e5c31af7Sopenharmony_ci												ContextShaderProgram		(const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays);
687e5c31af7Sopenharmony_ci
688e5c31af7Sopenharmony_ci	void										shadeVertices				(const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
689e5c31af7Sopenharmony_ci	void										shadeFragments				(rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ciprivate:
692e5c31af7Sopenharmony_ci	static std::string							genVertexSource				(const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays);
693e5c31af7Sopenharmony_ci	static std::string							genFragmentSource			(const glu::RenderContext& ctx);
694e5c31af7Sopenharmony_ci	static rr::GenericVecType					mapOutputType				(const Array::OutputType& type);
695e5c31af7Sopenharmony_ci	static int									getComponentCount			(const Array::OutputType& type);
696e5c31af7Sopenharmony_ci
697e5c31af7Sopenharmony_ci	static sglr::pdec::ShaderProgramDeclaration createProgramDeclaration	(const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays);
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci	std::vector<int>							m_componentCount;
700e5c31af7Sopenharmony_ci	std::vector<rr::GenericVecType>				m_attrType;
701e5c31af7Sopenharmony_ci};
702e5c31af7Sopenharmony_ci
703e5c31af7Sopenharmony_ciContextShaderProgram::ContextShaderProgram (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays)
704e5c31af7Sopenharmony_ci	: sglr::ShaderProgram	(createProgramDeclaration(ctx, arrays))
705e5c31af7Sopenharmony_ci	, m_componentCount		(arrays.size())
706e5c31af7Sopenharmony_ci	, m_attrType			(arrays.size())
707e5c31af7Sopenharmony_ci{
708e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
709e5c31af7Sopenharmony_ci	{
710e5c31af7Sopenharmony_ci		m_componentCount[arrayNdx]	= getComponentCount(arrays[arrayNdx]->getOutputType());
711e5c31af7Sopenharmony_ci		m_attrType[arrayNdx]		= mapOutputType(arrays[arrayNdx]->getOutputType());
712e5c31af7Sopenharmony_ci	}
713e5c31af7Sopenharmony_ci}
714e5c31af7Sopenharmony_ci
715e5c31af7Sopenharmony_citemplate <typename T>
716e5c31af7Sopenharmony_civoid calcShaderColorCoord (tcu::Vec2& coord, tcu::Vec3& color, const tcu::Vector<T, 4>& attribValue, bool isCoordinate, int numComponents)
717e5c31af7Sopenharmony_ci{
718e5c31af7Sopenharmony_ci	if (isCoordinate)
719e5c31af7Sopenharmony_ci		switch (numComponents)
720e5c31af7Sopenharmony_ci		{
721e5c31af7Sopenharmony_ci			case 1:	coord = tcu::Vec2((float)attribValue.x(),							(float)attribValue.x());							break;
722e5c31af7Sopenharmony_ci			case 2:	coord = tcu::Vec2((float)attribValue.x(),							(float)attribValue.y());							break;
723e5c31af7Sopenharmony_ci			case 3:	coord = tcu::Vec2((float)attribValue.x() + (float)attribValue.z(),	(float)attribValue.y());							break;
724e5c31af7Sopenharmony_ci			case 4:	coord = tcu::Vec2((float)attribValue.x() + (float)attribValue.z(),	(float)attribValue.y() + (float)attribValue.w());	break;
725e5c31af7Sopenharmony_ci
726e5c31af7Sopenharmony_ci			default:
727e5c31af7Sopenharmony_ci				DE_ASSERT(false);
728e5c31af7Sopenharmony_ci		}
729e5c31af7Sopenharmony_ci	else
730e5c31af7Sopenharmony_ci	{
731e5c31af7Sopenharmony_ci		switch (numComponents)
732e5c31af7Sopenharmony_ci		{
733e5c31af7Sopenharmony_ci			case 1:
734e5c31af7Sopenharmony_ci				color = color * (float)attribValue.x();
735e5c31af7Sopenharmony_ci				break;
736e5c31af7Sopenharmony_ci
737e5c31af7Sopenharmony_ci			case 2:
738e5c31af7Sopenharmony_ci				color.x() = color.x() * (float)attribValue.x();
739e5c31af7Sopenharmony_ci				color.y() = color.y() * (float)attribValue.y();
740e5c31af7Sopenharmony_ci				break;
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci			case 3:
743e5c31af7Sopenharmony_ci				color.x() = color.x() * (float)attribValue.x();
744e5c31af7Sopenharmony_ci				color.y() = color.y() * (float)attribValue.y();
745e5c31af7Sopenharmony_ci				color.z() = color.z() * (float)attribValue.z();
746e5c31af7Sopenharmony_ci				break;
747e5c31af7Sopenharmony_ci
748e5c31af7Sopenharmony_ci			case 4:
749e5c31af7Sopenharmony_ci				color.x() = color.x() * (float)attribValue.x() * (float)attribValue.w();
750e5c31af7Sopenharmony_ci				color.y() = color.y() * (float)attribValue.y() * (float)attribValue.w();
751e5c31af7Sopenharmony_ci				color.z() = color.z() * (float)attribValue.z() * (float)attribValue.w();
752e5c31af7Sopenharmony_ci				break;
753e5c31af7Sopenharmony_ci
754e5c31af7Sopenharmony_ci			default:
755e5c31af7Sopenharmony_ci				DE_ASSERT(false);
756e5c31af7Sopenharmony_ci		}
757e5c31af7Sopenharmony_ci	}
758e5c31af7Sopenharmony_ci}
759e5c31af7Sopenharmony_ci
760e5c31af7Sopenharmony_civoid ContextShaderProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
761e5c31af7Sopenharmony_ci{
762e5c31af7Sopenharmony_ci	const float	u_coordScale = getUniformByName("u_coordScale").value.f;
763e5c31af7Sopenharmony_ci	const float u_colorScale = getUniformByName("u_colorScale").value.f;
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ci	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
766e5c31af7Sopenharmony_ci	{
767e5c31af7Sopenharmony_ci		const size_t varyingLocColor = 0;
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_ci		rr::VertexPacket& packet = *packets[packetNdx];
770e5c31af7Sopenharmony_ci
771e5c31af7Sopenharmony_ci		// Calc output color
772e5c31af7Sopenharmony_ci		tcu::Vec2 coord = tcu::Vec2(1.0, 1.0);
773e5c31af7Sopenharmony_ci		tcu::Vec3 color = tcu::Vec3(1.0, 1.0, 1.0);
774e5c31af7Sopenharmony_ci
775e5c31af7Sopenharmony_ci		for (int attribNdx = 0; attribNdx < (int)m_attrType.size(); attribNdx++)
776e5c31af7Sopenharmony_ci		{
777e5c31af7Sopenharmony_ci			const int numComponents = m_componentCount[attribNdx];
778e5c31af7Sopenharmony_ci
779e5c31af7Sopenharmony_ci			switch (m_attrType[attribNdx])
780e5c31af7Sopenharmony_ci			{
781e5c31af7Sopenharmony_ci				case rr::GENERICVECTYPE_FLOAT:	calcShaderColorCoord(coord, color, rr::readVertexAttribFloat(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents);	break;
782e5c31af7Sopenharmony_ci				case rr::GENERICVECTYPE_INT32:	calcShaderColorCoord(coord, color, rr::readVertexAttribInt	(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents);	break;
783e5c31af7Sopenharmony_ci				case rr::GENERICVECTYPE_UINT32:	calcShaderColorCoord(coord, color, rr::readVertexAttribUint	(inputs[attribNdx], packet.instanceNdx, packet.vertexNdx), attribNdx == 0, numComponents);	break;
784e5c31af7Sopenharmony_ci				default:
785e5c31af7Sopenharmony_ci					DE_ASSERT(false);
786e5c31af7Sopenharmony_ci			}
787e5c31af7Sopenharmony_ci		}
788e5c31af7Sopenharmony_ci
789e5c31af7Sopenharmony_ci		// Transform position
790e5c31af7Sopenharmony_ci		{
791e5c31af7Sopenharmony_ci			packet.position = tcu::Vec4(u_coordScale * coord.x(), u_coordScale * coord.y(), 1.0f, 1.0f);
792e5c31af7Sopenharmony_ci		}
793e5c31af7Sopenharmony_ci
794e5c31af7Sopenharmony_ci		// Pass color to FS
795e5c31af7Sopenharmony_ci		{
796e5c31af7Sopenharmony_ci			packet.outputs[varyingLocColor] = tcu::Vec4(u_colorScale * color.x(), u_colorScale * color.y(), u_colorScale * color.z(), 1.0f);
797e5c31af7Sopenharmony_ci		}
798e5c31af7Sopenharmony_ci	}
799e5c31af7Sopenharmony_ci}
800e5c31af7Sopenharmony_ci
801e5c31af7Sopenharmony_civoid ContextShaderProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
802e5c31af7Sopenharmony_ci{
803e5c31af7Sopenharmony_ci	const size_t varyingLocColor = 0;
804e5c31af7Sopenharmony_ci
805e5c31af7Sopenharmony_ci	// Triangles are flashaded
806e5c31af7Sopenharmony_ci	tcu::Vec4 color = rr::readTriangleVarying<float>(packets[0], context, varyingLocColor, 0);
807e5c31af7Sopenharmony_ci
808e5c31af7Sopenharmony_ci	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
809e5c31af7Sopenharmony_ci		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
810e5c31af7Sopenharmony_ci			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
811e5c31af7Sopenharmony_ci}
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_cistd::string ContextShaderProgram::genVertexSource (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays)
814e5c31af7Sopenharmony_ci{
815e5c31af7Sopenharmony_ci	std::stringstream vertexShaderTmpl;
816e5c31af7Sopenharmony_ci	std::map<std::string, std::string> params;
817e5c31af7Sopenharmony_ci
818e5c31af7Sopenharmony_ci	if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_300_ES))
819e5c31af7Sopenharmony_ci	{
820e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "in";
821e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "out";
822e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "in";
823e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "dEQP_FragColor";
824e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "#version 300 es\n";
825e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
826e5c31af7Sopenharmony_ci	}
827e5c31af7Sopenharmony_ci	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_100_ES))
828e5c31af7Sopenharmony_ci	{
829e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "attribute";
830e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "varying";
831e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "varying";
832e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "gl_FragColor";
833e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "";
834e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "";
835e5c31af7Sopenharmony_ci	}
836e5c31af7Sopenharmony_ci	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_330))
837e5c31af7Sopenharmony_ci	{
838e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "in";
839e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "out";
840e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "in";
841e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "dEQP_FragColor";
842e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "#version 330\n";
843e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
844e5c31af7Sopenharmony_ci	}
845e5c31af7Sopenharmony_ci	else
846e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
847e5c31af7Sopenharmony_ci
848e5c31af7Sopenharmony_ci	vertexShaderTmpl << "${VTX_HDR}";
849e5c31af7Sopenharmony_ci
850e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
851e5c31af7Sopenharmony_ci	{
852e5c31af7Sopenharmony_ci		vertexShaderTmpl
853e5c31af7Sopenharmony_ci			<< "${VTX_IN} highp " <<  ContextArray::outputTypeToGLType(arrays[arrayNdx]->getOutputType()) << " a_" << arrays[arrayNdx]->getAttribNdx() << ";\n";
854e5c31af7Sopenharmony_ci	}
855e5c31af7Sopenharmony_ci
856e5c31af7Sopenharmony_ci	vertexShaderTmpl <<
857e5c31af7Sopenharmony_ci		"uniform highp float u_coordScale;\n"
858e5c31af7Sopenharmony_ci		"uniform highp float u_colorScale;\n"
859e5c31af7Sopenharmony_ci		"${VTX_OUT} mediump vec4 v_color;\n"
860e5c31af7Sopenharmony_ci		"void main(void)\n"
861e5c31af7Sopenharmony_ci		"{\n"
862e5c31af7Sopenharmony_ci		"\tgl_PointSize = 1.0;\n"
863e5c31af7Sopenharmony_ci		"\thighp vec2 coord = vec2(1.0, 1.0);\n"
864e5c31af7Sopenharmony_ci		"\thighp vec3 color = vec3(1.0, 1.0, 1.0);\n";
865e5c31af7Sopenharmony_ci
866e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
867e5c31af7Sopenharmony_ci	{
868e5c31af7Sopenharmony_ci		if (arrays[arrayNdx]->getAttribNdx() == 0)
869e5c31af7Sopenharmony_ci		{
870e5c31af7Sopenharmony_ci			switch (arrays[arrayNdx]->getOutputType())
871e5c31af7Sopenharmony_ci			{
872e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_FLOAT):
873e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
874e5c31af7Sopenharmony_ci						"\tcoord = vec2(a_0);\n";
875e5c31af7Sopenharmony_ci					break;
876e5c31af7Sopenharmony_ci
877e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_VEC2):
878e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
879e5c31af7Sopenharmony_ci						"\tcoord = a_0.xy;\n";
880e5c31af7Sopenharmony_ci					break;
881e5c31af7Sopenharmony_ci
882e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_VEC3):
883e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
884e5c31af7Sopenharmony_ci						"\tcoord = a_0.xy;\n"
885e5c31af7Sopenharmony_ci						"\tcoord.x = coord.x + a_0.z;\n";
886e5c31af7Sopenharmony_ci					break;
887e5c31af7Sopenharmony_ci
888e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_VEC4):
889e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
890e5c31af7Sopenharmony_ci						"\tcoord = a_0.xy;\n"
891e5c31af7Sopenharmony_ci						"\tcoord += a_0.zw;\n";
892e5c31af7Sopenharmony_ci					break;
893e5c31af7Sopenharmony_ci
894e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_IVEC2):
895e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_UVEC2):
896e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
897e5c31af7Sopenharmony_ci						"\tcoord = vec2(a_0.xy);\n";
898e5c31af7Sopenharmony_ci					break;
899e5c31af7Sopenharmony_ci
900e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_IVEC3):
901e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_UVEC3):
902e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
903e5c31af7Sopenharmony_ci						"\tcoord = vec2(a_0.xy);\n"
904e5c31af7Sopenharmony_ci						"\tcoord.x = coord.x + float(a_0.z);\n";
905e5c31af7Sopenharmony_ci					break;
906e5c31af7Sopenharmony_ci
907e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_IVEC4):
908e5c31af7Sopenharmony_ci				case (Array::OUTPUTTYPE_UVEC4):
909e5c31af7Sopenharmony_ci					vertexShaderTmpl <<
910e5c31af7Sopenharmony_ci						"\tcoord = vec2(a_0.xy);\n"
911e5c31af7Sopenharmony_ci						"\tcoord += vec2(a_0.zw);\n";
912e5c31af7Sopenharmony_ci					break;
913e5c31af7Sopenharmony_ci
914e5c31af7Sopenharmony_ci				default:
915e5c31af7Sopenharmony_ci					DE_ASSERT(false);
916e5c31af7Sopenharmony_ci					break;
917e5c31af7Sopenharmony_ci			}
918e5c31af7Sopenharmony_ci			continue;
919e5c31af7Sopenharmony_ci		}
920e5c31af7Sopenharmony_ci
921e5c31af7Sopenharmony_ci		switch (arrays[arrayNdx]->getOutputType())
922e5c31af7Sopenharmony_ci		{
923e5c31af7Sopenharmony_ci			case (Array::OUTPUTTYPE_FLOAT):
924e5c31af7Sopenharmony_ci				vertexShaderTmpl <<
925e5c31af7Sopenharmony_ci					"\tcolor = color * a_" << arrays[arrayNdx]->getAttribNdx() << ";\n";
926e5c31af7Sopenharmony_ci				break;
927e5c31af7Sopenharmony_ci
928e5c31af7Sopenharmony_ci			case (Array::OUTPUTTYPE_VEC2):
929e5c31af7Sopenharmony_ci				vertexShaderTmpl <<
930e5c31af7Sopenharmony_ci					"\tcolor.rg = color.rg * a_" << arrays[arrayNdx]->getAttribNdx() << ".xy;\n";
931e5c31af7Sopenharmony_ci				break;
932e5c31af7Sopenharmony_ci
933e5c31af7Sopenharmony_ci			case (Array::OUTPUTTYPE_VEC3):
934e5c31af7Sopenharmony_ci				vertexShaderTmpl <<
935e5c31af7Sopenharmony_ci					"\tcolor = color.rgb * a_" << arrays[arrayNdx]->getAttribNdx() << ".xyz;\n";
936e5c31af7Sopenharmony_ci				break;
937e5c31af7Sopenharmony_ci
938e5c31af7Sopenharmony_ci			case (Array::OUTPUTTYPE_VEC4):
939e5c31af7Sopenharmony_ci				vertexShaderTmpl <<
940e5c31af7Sopenharmony_ci					"\tcolor = color.rgb * a_" << arrays[arrayNdx]->getAttribNdx() << ".xyz * a_" << arrays[arrayNdx]->getAttribNdx() << ".w;\n";
941e5c31af7Sopenharmony_ci				break;
942e5c31af7Sopenharmony_ci
943e5c31af7Sopenharmony_ci			default:
944e5c31af7Sopenharmony_ci				DE_ASSERT(false);
945e5c31af7Sopenharmony_ci				break;
946e5c31af7Sopenharmony_ci		}
947e5c31af7Sopenharmony_ci	}
948e5c31af7Sopenharmony_ci
949e5c31af7Sopenharmony_ci	vertexShaderTmpl <<
950e5c31af7Sopenharmony_ci		"\tv_color = vec4(u_colorScale * color, 1.0);\n"
951e5c31af7Sopenharmony_ci		"\tgl_Position = vec4(u_coordScale * coord, 1.0, 1.0);\n"
952e5c31af7Sopenharmony_ci		"}\n";
953e5c31af7Sopenharmony_ci
954e5c31af7Sopenharmony_ci	return tcu::StringTemplate(vertexShaderTmpl.str().c_str()).specialize(params);
955e5c31af7Sopenharmony_ci}
956e5c31af7Sopenharmony_ci
957e5c31af7Sopenharmony_cistd::string ContextShaderProgram::genFragmentSource (const glu::RenderContext& ctx)
958e5c31af7Sopenharmony_ci{
959e5c31af7Sopenharmony_ci	std::map<std::string, std::string> params;
960e5c31af7Sopenharmony_ci
961e5c31af7Sopenharmony_ci	if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_300_ES))
962e5c31af7Sopenharmony_ci	{
963e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "in";
964e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "out";
965e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "in";
966e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "dEQP_FragColor";
967e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "#version 300 es\n";
968e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "#version 300 es\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
969e5c31af7Sopenharmony_ci	}
970e5c31af7Sopenharmony_ci	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_100_ES))
971e5c31af7Sopenharmony_ci	{
972e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "attribute";
973e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "varying";
974e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "varying";
975e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "gl_FragColor";
976e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "";
977e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "";
978e5c31af7Sopenharmony_ci	}
979e5c31af7Sopenharmony_ci	else if (glu::isGLSLVersionSupported(ctx.getType(), glu::GLSL_VERSION_330))
980e5c31af7Sopenharmony_ci	{
981e5c31af7Sopenharmony_ci		params["VTX_IN"]		= "in";
982e5c31af7Sopenharmony_ci		params["VTX_OUT"]		= "out";
983e5c31af7Sopenharmony_ci		params["FRAG_IN"]		= "in";
984e5c31af7Sopenharmony_ci		params["FRAG_COLOR"]	= "dEQP_FragColor";
985e5c31af7Sopenharmony_ci		params["VTX_HDR"]		= "#version 330\n";
986e5c31af7Sopenharmony_ci		params["FRAG_HDR"]		= "#version 330\nlayout(location = 0) out mediump vec4 dEQP_FragColor;\n";
987e5c31af7Sopenharmony_ci	}
988e5c31af7Sopenharmony_ci	else
989e5c31af7Sopenharmony_ci		DE_ASSERT(DE_FALSE);
990e5c31af7Sopenharmony_ci
991e5c31af7Sopenharmony_ci	static const char* fragmentShaderTmpl =
992e5c31af7Sopenharmony_ci		"${FRAG_HDR}"
993e5c31af7Sopenharmony_ci		"${FRAG_IN} mediump vec4 v_color;\n"
994e5c31af7Sopenharmony_ci		"void main(void)\n"
995e5c31af7Sopenharmony_ci		"{\n"
996e5c31af7Sopenharmony_ci		"\t${FRAG_COLOR} = v_color;\n"
997e5c31af7Sopenharmony_ci		"}\n";
998e5c31af7Sopenharmony_ci
999e5c31af7Sopenharmony_ci	return tcu::StringTemplate(fragmentShaderTmpl).specialize(params);
1000e5c31af7Sopenharmony_ci}
1001e5c31af7Sopenharmony_ci
1002e5c31af7Sopenharmony_cirr::GenericVecType ContextShaderProgram::mapOutputType (const Array::OutputType& type)
1003e5c31af7Sopenharmony_ci{
1004e5c31af7Sopenharmony_ci	switch (type)
1005e5c31af7Sopenharmony_ci	{
1006e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_FLOAT):
1007e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_VEC2):
1008e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_VEC3):
1009e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_VEC4):
1010e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_FLOAT;
1011e5c31af7Sopenharmony_ci
1012e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_INT):
1013e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_IVEC2):
1014e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_IVEC3):
1015e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_IVEC4):
1016e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_INT32;
1017e5c31af7Sopenharmony_ci
1018e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UINT):
1019e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UVEC2):
1020e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UVEC3):
1021e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UVEC4):
1022e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_UINT32;
1023e5c31af7Sopenharmony_ci
1024e5c31af7Sopenharmony_ci		default:
1025e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1026e5c31af7Sopenharmony_ci			return rr::GENERICVECTYPE_LAST;
1027e5c31af7Sopenharmony_ci	}
1028e5c31af7Sopenharmony_ci}
1029e5c31af7Sopenharmony_ci
1030e5c31af7Sopenharmony_ciint ContextShaderProgram::getComponentCount (const Array::OutputType& type)
1031e5c31af7Sopenharmony_ci{
1032e5c31af7Sopenharmony_ci	switch (type)
1033e5c31af7Sopenharmony_ci	{
1034e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_FLOAT):
1035e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_INT):
1036e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UINT):
1037e5c31af7Sopenharmony_ci			return 1;
1038e5c31af7Sopenharmony_ci
1039e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_VEC2):
1040e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_IVEC2):
1041e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UVEC2):
1042e5c31af7Sopenharmony_ci			return 2;
1043e5c31af7Sopenharmony_ci
1044e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_VEC3):
1045e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_IVEC3):
1046e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UVEC3):
1047e5c31af7Sopenharmony_ci			return 3;
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_VEC4):
1050e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_IVEC4):
1051e5c31af7Sopenharmony_ci		case (Array::OUTPUTTYPE_UVEC4):
1052e5c31af7Sopenharmony_ci			return 4;
1053e5c31af7Sopenharmony_ci
1054e5c31af7Sopenharmony_ci		default:
1055e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1056e5c31af7Sopenharmony_ci			return 0;
1057e5c31af7Sopenharmony_ci	}
1058e5c31af7Sopenharmony_ci}
1059e5c31af7Sopenharmony_ci
1060e5c31af7Sopenharmony_cisglr::pdec::ShaderProgramDeclaration ContextShaderProgram::createProgramDeclaration (const glu::RenderContext& ctx, const std::vector<ContextArray*>& arrays)
1061e5c31af7Sopenharmony_ci{
1062e5c31af7Sopenharmony_ci	sglr::pdec::ShaderProgramDeclaration decl;
1063e5c31af7Sopenharmony_ci
1064e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)arrays.size(); arrayNdx++)
1065e5c31af7Sopenharmony_ci		decl << sglr::pdec::VertexAttribute(std::string("a_") + de::toString(arrayNdx), mapOutputType(arrays[arrayNdx]->getOutputType()));
1066e5c31af7Sopenharmony_ci
1067e5c31af7Sopenharmony_ci	decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
1068e5c31af7Sopenharmony_ci	decl << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT);
1069e5c31af7Sopenharmony_ci
1070e5c31af7Sopenharmony_ci	decl << sglr::pdec::VertexSource(genVertexSource(ctx, arrays));
1071e5c31af7Sopenharmony_ci	decl << sglr::pdec::FragmentSource(genFragmentSource(ctx));
1072e5c31af7Sopenharmony_ci
1073e5c31af7Sopenharmony_ci	decl << sglr::pdec::Uniform("u_coordScale", glu::TYPE_FLOAT);
1074e5c31af7Sopenharmony_ci	decl << sglr::pdec::Uniform("u_colorScale", glu::TYPE_FLOAT);
1075e5c31af7Sopenharmony_ci
1076e5c31af7Sopenharmony_ci	return decl;
1077e5c31af7Sopenharmony_ci}
1078e5c31af7Sopenharmony_ci
1079e5c31af7Sopenharmony_civoid ContextArrayPack::updateProgram (void)
1080e5c31af7Sopenharmony_ci{
1081e5c31af7Sopenharmony_ci	delete m_program;
1082e5c31af7Sopenharmony_ci	m_program = new ContextShaderProgram(m_renderCtx, m_arrays);
1083e5c31af7Sopenharmony_ci}
1084e5c31af7Sopenharmony_ci
1085e5c31af7Sopenharmony_civoid ContextArrayPack::render (Array::Primitive primitive, int firstVertex, int vertexCount, bool useVao, float coordScale, float colorScale)
1086e5c31af7Sopenharmony_ci{
1087e5c31af7Sopenharmony_ci	deUint32 program = 0;
1088e5c31af7Sopenharmony_ci	deUint32 vaoId = 0;
1089e5c31af7Sopenharmony_ci
1090e5c31af7Sopenharmony_ci	updateProgram();
1091e5c31af7Sopenharmony_ci
1092e5c31af7Sopenharmony_ci	m_ctx.viewport(0, 0, m_screen.getWidth(), m_screen.getHeight());
1093e5c31af7Sopenharmony_ci	m_ctx.clearColor(0.0, 0.0, 0.0, 1.0);
1094e5c31af7Sopenharmony_ci	m_ctx.clear(GL_COLOR_BUFFER_BIT);
1095e5c31af7Sopenharmony_ci
1096e5c31af7Sopenharmony_ci	program = m_ctx.createProgram(m_program);
1097e5c31af7Sopenharmony_ci
1098e5c31af7Sopenharmony_ci	m_ctx.useProgram(program);
1099e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glUseProgram()");
1100e5c31af7Sopenharmony_ci
1101e5c31af7Sopenharmony_ci	m_ctx.uniform1f(m_ctx.getUniformLocation(program, "u_coordScale"), coordScale);
1102e5c31af7Sopenharmony_ci	m_ctx.uniform1f(m_ctx.getUniformLocation(program, "u_colorScale"), colorScale);
1103e5c31af7Sopenharmony_ci
1104e5c31af7Sopenharmony_ci	if (useVao)
1105e5c31af7Sopenharmony_ci	{
1106e5c31af7Sopenharmony_ci		m_ctx.genVertexArrays(1, &vaoId);
1107e5c31af7Sopenharmony_ci		m_ctx.bindVertexArray(vaoId);
1108e5c31af7Sopenharmony_ci	}
1109e5c31af7Sopenharmony_ci
1110e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
1111e5c31af7Sopenharmony_ci	{
1112e5c31af7Sopenharmony_ci		if (m_arrays[arrayNdx]->isBound())
1113e5c31af7Sopenharmony_ci		{
1114e5c31af7Sopenharmony_ci			std::stringstream attribName;
1115e5c31af7Sopenharmony_ci			attribName << "a_" << m_arrays[arrayNdx]->getAttribNdx();
1116e5c31af7Sopenharmony_ci
1117e5c31af7Sopenharmony_ci			deUint32 loc = m_ctx.getAttribLocation(program, attribName.str().c_str());
1118e5c31af7Sopenharmony_ci			m_ctx.enableVertexAttribArray(loc);
1119e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glEnableVertexAttribArray()");
1120e5c31af7Sopenharmony_ci
1121e5c31af7Sopenharmony_ci			m_arrays[arrayNdx]->glBind(loc);
1122e5c31af7Sopenharmony_ci		}
1123e5c31af7Sopenharmony_ci	}
1124e5c31af7Sopenharmony_ci
1125e5c31af7Sopenharmony_ci	DE_ASSERT((firstVertex % 6) == 0);
1126e5c31af7Sopenharmony_ci	m_ctx.drawArrays(ContextArray::primitiveToGL(primitive), firstVertex, vertexCount - firstVertex);
1127e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDrawArrays()");
1128e5c31af7Sopenharmony_ci
1129e5c31af7Sopenharmony_ci	for (int arrayNdx = 0; arrayNdx < (int)m_arrays.size(); arrayNdx++)
1130e5c31af7Sopenharmony_ci	{
1131e5c31af7Sopenharmony_ci		if (m_arrays[arrayNdx]->isBound())
1132e5c31af7Sopenharmony_ci		{
1133e5c31af7Sopenharmony_ci			std::stringstream attribName;
1134e5c31af7Sopenharmony_ci			attribName << "a_" << m_arrays[arrayNdx]->getAttribNdx();
1135e5c31af7Sopenharmony_ci
1136e5c31af7Sopenharmony_ci			deUint32 loc = m_ctx.getAttribLocation(program, attribName.str().c_str());
1137e5c31af7Sopenharmony_ci
1138e5c31af7Sopenharmony_ci			m_ctx.disableVertexAttribArray(loc);
1139e5c31af7Sopenharmony_ci			GLU_EXPECT_NO_ERROR(m_ctx.getError(), "glDisableVertexAttribArray()");
1140e5c31af7Sopenharmony_ci		}
1141e5c31af7Sopenharmony_ci	}
1142e5c31af7Sopenharmony_ci
1143e5c31af7Sopenharmony_ci	if (useVao)
1144e5c31af7Sopenharmony_ci		m_ctx.deleteVertexArrays(1, &vaoId);
1145e5c31af7Sopenharmony_ci
1146e5c31af7Sopenharmony_ci	m_ctx.deleteProgram(program);
1147e5c31af7Sopenharmony_ci	m_ctx.useProgram(0);
1148e5c31af7Sopenharmony_ci	m_ctx.readPixels(m_screen, 0, 0, m_screen.getWidth(), m_screen.getHeight());
1149e5c31af7Sopenharmony_ci}
1150e5c31af7Sopenharmony_ci
1151e5c31af7Sopenharmony_ci// GLValue
1152e5c31af7Sopenharmony_ci
1153e5c31af7Sopenharmony_ciGLValue GLValue::getMaxValue (Array::InputType type)
1154e5c31af7Sopenharmony_ci{
1155e5c31af7Sopenharmony_ci	GLValue rangesHi[(int)Array::INPUTTYPE_LAST];
1156e5c31af7Sopenharmony_ci
1157e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_FLOAT]			= GLValue(Float::create(127.0f));
1158e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_DOUBLE]			= GLValue(Double::create(127.0f));
1159e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_BYTE]			= GLValue(Byte::create(127));
1160e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_UNSIGNED_BYTE]	= GLValue(Ubyte::create(255));
1161e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_UNSIGNED_SHORT]	= GLValue(Ushort::create(65530));
1162e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_SHORT]			= GLValue(Short::create(32760));
1163e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_FIXED]			= GLValue(Fixed::create(32760));
1164e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_INT]				= GLValue(Int::create(2147483647));
1165e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_UNSIGNED_INT]	= GLValue(Uint::create(4294967295u));
1166e5c31af7Sopenharmony_ci	rangesHi[(int)Array::INPUTTYPE_HALF]			= GLValue(Half::create(256.0f));
1167e5c31af7Sopenharmony_ci
1168e5c31af7Sopenharmony_ci	return rangesHi[(int)type];
1169e5c31af7Sopenharmony_ci}
1170e5c31af7Sopenharmony_ci
1171e5c31af7Sopenharmony_ciGLValue GLValue::getMinValue (Array::InputType type)
1172e5c31af7Sopenharmony_ci{
1173e5c31af7Sopenharmony_ci	GLValue rangesLo[(int)Array::INPUTTYPE_LAST];
1174e5c31af7Sopenharmony_ci
1175e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_FLOAT]			= GLValue(Float::create(-127.0f));
1176e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_DOUBLE]			= GLValue(Double::create(-127.0f));
1177e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_BYTE]			= GLValue(Byte::create(-127));
1178e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_UNSIGNED_BYTE]	= GLValue(Ubyte::create(0));
1179e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_UNSIGNED_SHORT]	= GLValue(Ushort::create(0));
1180e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_SHORT]			= GLValue(Short::create(-32760));
1181e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_FIXED]			= GLValue(Fixed::create(-32760));
1182e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_INT]				= GLValue(Int::create(-2147483647));
1183e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_UNSIGNED_INT]	= GLValue(Uint::create(0));
1184e5c31af7Sopenharmony_ci	rangesLo[(int)Array::INPUTTYPE_HALF]			= GLValue(Half::create(-256.0f));
1185e5c31af7Sopenharmony_ci
1186e5c31af7Sopenharmony_ci	return rangesLo[(int)type];
1187e5c31af7Sopenharmony_ci}
1188e5c31af7Sopenharmony_ci
1189e5c31af7Sopenharmony_cifloat GLValue::toFloat (void) const
1190e5c31af7Sopenharmony_ci{
1191e5c31af7Sopenharmony_ci	switch (type)
1192e5c31af7Sopenharmony_ci	{
1193e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FLOAT:
1194e5c31af7Sopenharmony_ci			return fl.getValue();
1195e5c31af7Sopenharmony_ci
1196e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_BYTE:
1197e5c31af7Sopenharmony_ci			return b.getValue();
1198e5c31af7Sopenharmony_ci
1199e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_BYTE:
1200e5c31af7Sopenharmony_ci			return ub.getValue();
1201e5c31af7Sopenharmony_ci
1202e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_SHORT:
1203e5c31af7Sopenharmony_ci			return s.getValue();
1204e5c31af7Sopenharmony_ci
1205e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_SHORT:
1206e5c31af7Sopenharmony_ci			return us.getValue();
1207e5c31af7Sopenharmony_ci
1208e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FIXED:
1209e5c31af7Sopenharmony_ci		{
1210e5c31af7Sopenharmony_ci			int maxValue = 65536;
1211e5c31af7Sopenharmony_ci			return (float)(double(2 * fi.getValue() + 1) / (maxValue - 1));
1212e5c31af7Sopenharmony_ci		}
1213e5c31af7Sopenharmony_ci
1214e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_INT:
1215e5c31af7Sopenharmony_ci			return (float)ui.getValue();
1216e5c31af7Sopenharmony_ci
1217e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_INT:
1218e5c31af7Sopenharmony_ci			return (float)i.getValue();
1219e5c31af7Sopenharmony_ci
1220e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_HALF:
1221e5c31af7Sopenharmony_ci			return h.to<float>();
1222e5c31af7Sopenharmony_ci
1223e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_DOUBLE:
1224e5c31af7Sopenharmony_ci			return (float)d.getValue();
1225e5c31af7Sopenharmony_ci
1226e5c31af7Sopenharmony_ci		default:
1227e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1228e5c31af7Sopenharmony_ci			return 0.0f;
1229e5c31af7Sopenharmony_ci	}
1230e5c31af7Sopenharmony_ci}
1231e5c31af7Sopenharmony_ci
1232e5c31af7Sopenharmony_ciclass RandomArrayGenerator
1233e5c31af7Sopenharmony_ci{
1234e5c31af7Sopenharmony_cipublic:
1235e5c31af7Sopenharmony_ci	static char*	generateArray			(int seed, GLValue min, GLValue max, int count, int componentCount, int stride, Array::InputType type);
1236e5c31af7Sopenharmony_ci	static char*	generateQuads			(int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max, float gridSize);
1237e5c31af7Sopenharmony_ci	static char*	generatePerQuad			(int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max);
1238e5c31af7Sopenharmony_ci
1239e5c31af7Sopenharmony_ciprivate:
1240e5c31af7Sopenharmony_ci	template<typename T>
1241e5c31af7Sopenharmony_ci	static char*	createQuads		(int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max, float gridSize);
1242e5c31af7Sopenharmony_ci	template<typename T>
1243e5c31af7Sopenharmony_ci	static char*	createPerQuads	(int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max);
1244e5c31af7Sopenharmony_ci	static char*	createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive);
1245e5c31af7Sopenharmony_ci	static void		setData			(char* data, Array::InputType type, deRandom& rnd, GLValue min, GLValue max);
1246e5c31af7Sopenharmony_ci};
1247e5c31af7Sopenharmony_ci
1248e5c31af7Sopenharmony_civoid RandomArrayGenerator::setData (char* data, Array::InputType type, deRandom& rnd, GLValue min, GLValue max)
1249e5c31af7Sopenharmony_ci{
1250e5c31af7Sopenharmony_ci	switch (type)
1251e5c31af7Sopenharmony_ci	{
1252e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FLOAT:
1253e5c31af7Sopenharmony_ci		{
1254e5c31af7Sopenharmony_ci			alignmentSafeAssignment<float>(data, getRandom<GLValue::Float>(rnd, min.fl, max.fl));
1255e5c31af7Sopenharmony_ci			break;
1256e5c31af7Sopenharmony_ci		}
1257e5c31af7Sopenharmony_ci
1258e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_DOUBLE:
1259e5c31af7Sopenharmony_ci		{
1260e5c31af7Sopenharmony_ci			alignmentSafeAssignment<double>(data, getRandom<GLValue::Float>(rnd, min.fl, max.fl));
1261e5c31af7Sopenharmony_ci			break;
1262e5c31af7Sopenharmony_ci		}
1263e5c31af7Sopenharmony_ci
1264e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_SHORT:
1265e5c31af7Sopenharmony_ci		{
1266e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deInt16>(data, getRandom<GLValue::Short>(rnd, min.s, max.s));
1267e5c31af7Sopenharmony_ci			break;
1268e5c31af7Sopenharmony_ci		}
1269e5c31af7Sopenharmony_ci
1270e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_SHORT:
1271e5c31af7Sopenharmony_ci		{
1272e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deUint16>(data, getRandom<GLValue::Ushort>(rnd, min.us, max.us));
1273e5c31af7Sopenharmony_ci			break;
1274e5c31af7Sopenharmony_ci		}
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_BYTE:
1277e5c31af7Sopenharmony_ci		{
1278e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deInt8>(data, getRandom<GLValue::Byte>(rnd, min.b, max.b));
1279e5c31af7Sopenharmony_ci			break;
1280e5c31af7Sopenharmony_ci		}
1281e5c31af7Sopenharmony_ci
1282e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_BYTE:
1283e5c31af7Sopenharmony_ci		{
1284e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deUint8>(data, getRandom<GLValue::Ubyte>(rnd, min.ub, max.ub));
1285e5c31af7Sopenharmony_ci			break;
1286e5c31af7Sopenharmony_ci		}
1287e5c31af7Sopenharmony_ci
1288e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FIXED:
1289e5c31af7Sopenharmony_ci		{
1290e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deInt32>(data, getRandom<GLValue::Fixed>(rnd, min.fi, max.fi));
1291e5c31af7Sopenharmony_ci			break;
1292e5c31af7Sopenharmony_ci		}
1293e5c31af7Sopenharmony_ci
1294e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_INT:
1295e5c31af7Sopenharmony_ci		{
1296e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deInt32>(data, getRandom<GLValue::Int>(rnd, min.i, max.i));
1297e5c31af7Sopenharmony_ci			break;
1298e5c31af7Sopenharmony_ci		}
1299e5c31af7Sopenharmony_ci
1300e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_INT:
1301e5c31af7Sopenharmony_ci		{
1302e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deUint32>(data, getRandom<GLValue::Uint>(rnd, min.ui, max.ui));
1303e5c31af7Sopenharmony_ci			break;
1304e5c31af7Sopenharmony_ci		}
1305e5c31af7Sopenharmony_ci
1306e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_HALF:
1307e5c31af7Sopenharmony_ci		{
1308e5c31af7Sopenharmony_ci			alignmentSafeAssignment<deFloat16>(data, getRandom<GLValue::Half>(rnd, min.h, max.h).getValue());
1309e5c31af7Sopenharmony_ci			break;
1310e5c31af7Sopenharmony_ci		}
1311e5c31af7Sopenharmony_ci
1312e5c31af7Sopenharmony_ci		default:
1313e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1314e5c31af7Sopenharmony_ci			break;
1315e5c31af7Sopenharmony_ci	}
1316e5c31af7Sopenharmony_ci}
1317e5c31af7Sopenharmony_ci
1318e5c31af7Sopenharmony_cichar* RandomArrayGenerator::generateArray (int seed, GLValue min, GLValue max, int count, int componentCount, int stride, Array::InputType type)
1319e5c31af7Sopenharmony_ci{
1320e5c31af7Sopenharmony_ci	char* data = NULL;
1321e5c31af7Sopenharmony_ci
1322e5c31af7Sopenharmony_ci	deRandom rnd;
1323e5c31af7Sopenharmony_ci	deRandom_init(&rnd, seed);
1324e5c31af7Sopenharmony_ci
1325e5c31af7Sopenharmony_ci	if (stride == 0)
1326e5c31af7Sopenharmony_ci		stride = componentCount * Array::inputTypeSize(type);
1327e5c31af7Sopenharmony_ci
1328e5c31af7Sopenharmony_ci	data = new char[stride * count];
1329e5c31af7Sopenharmony_ci
1330e5c31af7Sopenharmony_ci	for (int vertexNdx = 0; vertexNdx < count; vertexNdx++)
1331e5c31af7Sopenharmony_ci	{
1332e5c31af7Sopenharmony_ci		for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1333e5c31af7Sopenharmony_ci		{
1334e5c31af7Sopenharmony_ci			setData(&(data[vertexNdx * stride + Array::inputTypeSize(type) * componentNdx]), type, rnd, min, max);
1335e5c31af7Sopenharmony_ci		}
1336e5c31af7Sopenharmony_ci	}
1337e5c31af7Sopenharmony_ci
1338e5c31af7Sopenharmony_ci	return data;
1339e5c31af7Sopenharmony_ci}
1340e5c31af7Sopenharmony_ci
1341e5c31af7Sopenharmony_cichar* RandomArrayGenerator::generateQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max, float gridSize)
1342e5c31af7Sopenharmony_ci{
1343e5c31af7Sopenharmony_ci	char* data = DE_NULL;
1344e5c31af7Sopenharmony_ci
1345e5c31af7Sopenharmony_ci	switch (type)
1346e5c31af7Sopenharmony_ci	{
1347e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FLOAT:
1348e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Float>(seed, count, componentCount, offset, stride, primitive, min.fl, max.fl, gridSize);
1349e5c31af7Sopenharmony_ci			break;
1350e5c31af7Sopenharmony_ci
1351e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FIXED:
1352e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Fixed>(seed, count, componentCount, offset, stride, primitive, min.fi, max.fi, gridSize);
1353e5c31af7Sopenharmony_ci			break;
1354e5c31af7Sopenharmony_ci
1355e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_DOUBLE:
1356e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Double>(seed, count, componentCount, offset, stride, primitive, min.d, max.d, gridSize);
1357e5c31af7Sopenharmony_ci			break;
1358e5c31af7Sopenharmony_ci
1359e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_BYTE:
1360e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Byte>(seed, count, componentCount, offset, stride, primitive, min.b, max.b, gridSize);
1361e5c31af7Sopenharmony_ci			break;
1362e5c31af7Sopenharmony_ci
1363e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_SHORT:
1364e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Short>(seed, count, componentCount, offset, stride, primitive, min.s, max.s, gridSize);
1365e5c31af7Sopenharmony_ci			break;
1366e5c31af7Sopenharmony_ci
1367e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_BYTE:
1368e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Ubyte>(seed, count, componentCount, offset, stride, primitive, min.ub, max.ub, gridSize);
1369e5c31af7Sopenharmony_ci			break;
1370e5c31af7Sopenharmony_ci
1371e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_SHORT:
1372e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Ushort>(seed, count, componentCount, offset, stride, primitive, min.us, max.us, gridSize);
1373e5c31af7Sopenharmony_ci			break;
1374e5c31af7Sopenharmony_ci
1375e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_INT:
1376e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Uint>(seed, count, componentCount, offset, stride, primitive, min.ui, max.ui, gridSize);
1377e5c31af7Sopenharmony_ci			break;
1378e5c31af7Sopenharmony_ci
1379e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_INT:
1380e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Int>(seed, count, componentCount, offset, stride, primitive, min.i, max.i, gridSize);
1381e5c31af7Sopenharmony_ci			break;
1382e5c31af7Sopenharmony_ci
1383e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_HALF:
1384e5c31af7Sopenharmony_ci			data = createQuads<GLValue::Half>(seed, count, componentCount, offset, stride, primitive, min.h, max.h, gridSize);
1385e5c31af7Sopenharmony_ci			break;
1386e5c31af7Sopenharmony_ci
1387e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_INT_2_10_10_10:
1388e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10:
1389e5c31af7Sopenharmony_ci			data = createQuadsPacked(seed, count, componentCount, offset, stride, primitive);
1390e5c31af7Sopenharmony_ci			break;
1391e5c31af7Sopenharmony_ci
1392e5c31af7Sopenharmony_ci		default:
1393e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1394e5c31af7Sopenharmony_ci			break;
1395e5c31af7Sopenharmony_ci	}
1396e5c31af7Sopenharmony_ci
1397e5c31af7Sopenharmony_ci	return data;
1398e5c31af7Sopenharmony_ci}
1399e5c31af7Sopenharmony_ci
1400e5c31af7Sopenharmony_cichar* RandomArrayGenerator::createQuadsPacked (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive)
1401e5c31af7Sopenharmony_ci{
1402e5c31af7Sopenharmony_ci	DE_ASSERT(componentCount == 4);
1403e5c31af7Sopenharmony_ci	DE_UNREF(componentCount);
1404e5c31af7Sopenharmony_ci	int quadStride = 0;
1405e5c31af7Sopenharmony_ci
1406e5c31af7Sopenharmony_ci	if (stride == 0)
1407e5c31af7Sopenharmony_ci		stride = sizeof(deUint32);
1408e5c31af7Sopenharmony_ci
1409e5c31af7Sopenharmony_ci	switch (primitive)
1410e5c31af7Sopenharmony_ci	{
1411e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_TRIANGLES:
1412e5c31af7Sopenharmony_ci			quadStride = stride * 6;
1413e5c31af7Sopenharmony_ci			break;
1414e5c31af7Sopenharmony_ci
1415e5c31af7Sopenharmony_ci		default:
1416e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1417e5c31af7Sopenharmony_ci			break;
1418e5c31af7Sopenharmony_ci	}
1419e5c31af7Sopenharmony_ci
1420e5c31af7Sopenharmony_ci	char* const _data		= new char[offset + quadStride * (count - 1) + stride * 5 + componentCount * Array::inputTypeSize(Array::INPUTTYPE_INT_2_10_10_10)]; // last element must be fully in the array
1421e5c31af7Sopenharmony_ci	char* const resultData	= _data + offset;
1422e5c31af7Sopenharmony_ci
1423e5c31af7Sopenharmony_ci	const deUint32 max		= 1024;
1424e5c31af7Sopenharmony_ci	const deUint32 min		= 10;
1425e5c31af7Sopenharmony_ci	const deUint32 max2		= 4;
1426e5c31af7Sopenharmony_ci
1427e5c31af7Sopenharmony_ci	deRandom rnd;
1428e5c31af7Sopenharmony_ci	deRandom_init(&rnd,  seed);
1429e5c31af7Sopenharmony_ci
1430e5c31af7Sopenharmony_ci	switch (primitive)
1431e5c31af7Sopenharmony_ci	{
1432e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_TRIANGLES:
1433e5c31af7Sopenharmony_ci		{
1434e5c31af7Sopenharmony_ci			for (int quadNdx = 0; quadNdx < count; quadNdx++)
1435e5c31af7Sopenharmony_ci			{
1436e5c31af7Sopenharmony_ci				deUint32 x1	= min + deRandom_getUint32(&rnd) % (max - min);
1437e5c31af7Sopenharmony_ci				deUint32 x2	= min + deRandom_getUint32(&rnd) % (max - x1);
1438e5c31af7Sopenharmony_ci
1439e5c31af7Sopenharmony_ci				deUint32 y1	= min + deRandom_getUint32(&rnd) % (max - min);
1440e5c31af7Sopenharmony_ci				deUint32 y2	= min + deRandom_getUint32(&rnd) % (max - y1);
1441e5c31af7Sopenharmony_ci
1442e5c31af7Sopenharmony_ci				deUint32 z	= min + deRandom_getUint32(&rnd) % (max - min);
1443e5c31af7Sopenharmony_ci				deUint32 w	= deRandom_getUint32(&rnd) % max2;
1444e5c31af7Sopenharmony_ci
1445e5c31af7Sopenharmony_ci				deUint32 val1 = (w << 30) | (z << 20) | (y1 << 10) | x1;
1446e5c31af7Sopenharmony_ci				deUint32 val2 = (w << 30) | (z << 20) | (y1 << 10) | x2;
1447e5c31af7Sopenharmony_ci				deUint32 val3 = (w << 30) | (z << 20) | (y2 << 10) | x1;
1448e5c31af7Sopenharmony_ci
1449e5c31af7Sopenharmony_ci				deUint32 val4 = (w << 30) | (z << 20) | (y2 << 10) | x1;
1450e5c31af7Sopenharmony_ci				deUint32 val5 = (w << 30) | (z << 20) | (y1 << 10) | x2;
1451e5c31af7Sopenharmony_ci				deUint32 val6 = (w << 30) | (z << 20) | (y2 << 10) | x2;
1452e5c31af7Sopenharmony_ci
1453e5c31af7Sopenharmony_ci				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 0]), val1);
1454e5c31af7Sopenharmony_ci				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 1]), val2);
1455e5c31af7Sopenharmony_ci				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 2]), val3);
1456e5c31af7Sopenharmony_ci				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 3]), val4);
1457e5c31af7Sopenharmony_ci				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 4]), val5);
1458e5c31af7Sopenharmony_ci				alignmentSafeAssignment<deUint32>(&(resultData[quadNdx * quadStride + stride * 5]), val6);
1459e5c31af7Sopenharmony_ci			}
1460e5c31af7Sopenharmony_ci
1461e5c31af7Sopenharmony_ci			break;
1462e5c31af7Sopenharmony_ci		}
1463e5c31af7Sopenharmony_ci
1464e5c31af7Sopenharmony_ci		default:
1465e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1466e5c31af7Sopenharmony_ci			break;
1467e5c31af7Sopenharmony_ci	}
1468e5c31af7Sopenharmony_ci
1469e5c31af7Sopenharmony_ci	return _data;
1470e5c31af7Sopenharmony_ci}
1471e5c31af7Sopenharmony_ci
1472e5c31af7Sopenharmony_citemplate<typename T>
1473e5c31af7Sopenharmony_ciT roundTo (const T& step, const T& value)
1474e5c31af7Sopenharmony_ci{
1475e5c31af7Sopenharmony_ci	return value - (value % step);
1476e5c31af7Sopenharmony_ci}
1477e5c31af7Sopenharmony_ci
1478e5c31af7Sopenharmony_citemplate<typename T>
1479e5c31af7Sopenharmony_cichar* RandomArrayGenerator::createQuads (int seed, int count, int componentCount, int offset, int stride, Array::Primitive primitive, T min, T max, float gridSize)
1480e5c31af7Sopenharmony_ci{
1481e5c31af7Sopenharmony_ci	int componentStride = sizeof(T);
1482e5c31af7Sopenharmony_ci	int quadStride = 0;
1483e5c31af7Sopenharmony_ci
1484e5c31af7Sopenharmony_ci	if (stride == 0)
1485e5c31af7Sopenharmony_ci		stride = componentCount * componentStride;
1486e5c31af7Sopenharmony_ci
1487e5c31af7Sopenharmony_ci	DE_ASSERT(stride >= componentCount * componentStride);
1488e5c31af7Sopenharmony_ci
1489e5c31af7Sopenharmony_ci	switch (primitive)
1490e5c31af7Sopenharmony_ci	{
1491e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_TRIANGLES:
1492e5c31af7Sopenharmony_ci			quadStride = stride * 6;
1493e5c31af7Sopenharmony_ci			break;
1494e5c31af7Sopenharmony_ci
1495e5c31af7Sopenharmony_ci		default:
1496e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1497e5c31af7Sopenharmony_ci			break;
1498e5c31af7Sopenharmony_ci	}
1499e5c31af7Sopenharmony_ci
1500e5c31af7Sopenharmony_ci	char* resultData = new char[offset + quadStride * count];
1501e5c31af7Sopenharmony_ci	char* _data = resultData;
1502e5c31af7Sopenharmony_ci	resultData = resultData + offset;
1503e5c31af7Sopenharmony_ci
1504e5c31af7Sopenharmony_ci	deRandom rnd;
1505e5c31af7Sopenharmony_ci	deRandom_init(&rnd,  seed);
1506e5c31af7Sopenharmony_ci
1507e5c31af7Sopenharmony_ci	switch (primitive)
1508e5c31af7Sopenharmony_ci	{
1509e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_TRIANGLES:
1510e5c31af7Sopenharmony_ci		{
1511e5c31af7Sopenharmony_ci			const T	minQuadSize	= T::fromFloat(deFloatAbs(max.template to<float>() - min.template to<float>()) * gridSize);
1512e5c31af7Sopenharmony_ci			const T	minDiff		= minValue<T>() > minQuadSize
1513e5c31af7Sopenharmony_ci								? minValue<T>()
1514e5c31af7Sopenharmony_ci								: minQuadSize;
1515e5c31af7Sopenharmony_ci			const T maxRounded	= roundTo(minDiff, max);
1516e5c31af7Sopenharmony_ci
1517e5c31af7Sopenharmony_ci			for (int quadNdx = 0; quadNdx < count; ++quadNdx)
1518e5c31af7Sopenharmony_ci			{
1519e5c31af7Sopenharmony_ci				T x1, x2;
1520e5c31af7Sopenharmony_ci				T y1, y2;
1521e5c31af7Sopenharmony_ci				T z, w;
1522e5c31af7Sopenharmony_ci
1523e5c31af7Sopenharmony_ci				x1 = roundTo(minDiff, getRandom<T>(rnd, min, maxRounded - minDiff));
1524e5c31af7Sopenharmony_ci				x2 = roundTo(minDiff, getRandom<T>(rnd, x1 + minDiff, maxRounded));
1525e5c31af7Sopenharmony_ci
1526e5c31af7Sopenharmony_ci				y1 = roundTo(minDiff, getRandom<T>(rnd, min, maxRounded - minDiff));
1527e5c31af7Sopenharmony_ci				y2 = roundTo(minDiff, getRandom<T>(rnd, y1 + minDiff, maxRounded));
1528e5c31af7Sopenharmony_ci
1529e5c31af7Sopenharmony_ci				// Make sure the rounding doesn't drop the result below the original range of the random function.
1530e5c31af7Sopenharmony_ci				if (x2 < x1 + minDiff) x2 = x1 + minDiff;
1531e5c31af7Sopenharmony_ci				if (y2 < y1 + minDiff) y2 = y1 + minDiff;
1532e5c31af7Sopenharmony_ci
1533e5c31af7Sopenharmony_ci				z = (componentCount > 2) ? roundTo(minDiff, (getRandom<T>(rnd, min, max))) : (T::create(0));
1534e5c31af7Sopenharmony_ci				w = (componentCount > 3) ? roundTo(minDiff, (getRandom<T>(rnd, min, max))) : (T::create(1));
1535e5c31af7Sopenharmony_ci
1536e5c31af7Sopenharmony_ci				// Make sure the quad is not too thin.
1537e5c31af7Sopenharmony_ci				DE_ASSERT((deFloatAbs(x2.template to<float>() - x1.template to<float>()) >= minDiff.template to<float>() * 0.8f) &&
1538e5c31af7Sopenharmony_ci					(deFloatAbs(y2.template to<float>() - y1.template to<float>()) >= minDiff.template to<float>() * 0.8f));
1539e5c31af7Sopenharmony_ci
1540e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride]), x1);
1541e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + componentStride]), y1);
1542e5c31af7Sopenharmony_ci
1543e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride]), x2);
1544e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride + componentStride]), y1);
1545e5c31af7Sopenharmony_ci
1546e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 2]), x1);
1547e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 2 + componentStride]), y2);
1548e5c31af7Sopenharmony_ci
1549e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 3]), x1);
1550e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 3 + componentStride]), y2);
1551e5c31af7Sopenharmony_ci
1552e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 4]), x2);
1553e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 4 + componentStride]), y1);
1554e5c31af7Sopenharmony_ci
1555e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 5]), x2);
1556e5c31af7Sopenharmony_ci				alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * 5 + componentStride]), y2);
1557e5c31af7Sopenharmony_ci
1558e5c31af7Sopenharmony_ci				if (componentCount > 2)
1559e5c31af7Sopenharmony_ci				{
1560e5c31af7Sopenharmony_ci					for (int i = 0; i < 6; i++)
1561e5c31af7Sopenharmony_ci						alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * i + componentStride * 2]), z);
1562e5c31af7Sopenharmony_ci				}
1563e5c31af7Sopenharmony_ci
1564e5c31af7Sopenharmony_ci				if (componentCount > 3)
1565e5c31af7Sopenharmony_ci				{
1566e5c31af7Sopenharmony_ci					for (int i = 0; i < 6; i++)
1567e5c31af7Sopenharmony_ci						alignmentSafeAssignment<T>(&(resultData[quadNdx * quadStride + stride * i + componentStride * 3]), w);
1568e5c31af7Sopenharmony_ci				}
1569e5c31af7Sopenharmony_ci			}
1570e5c31af7Sopenharmony_ci
1571e5c31af7Sopenharmony_ci			break;
1572e5c31af7Sopenharmony_ci		}
1573e5c31af7Sopenharmony_ci
1574e5c31af7Sopenharmony_ci		default:
1575e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1576e5c31af7Sopenharmony_ci			break;
1577e5c31af7Sopenharmony_ci	}
1578e5c31af7Sopenharmony_ci
1579e5c31af7Sopenharmony_ci	return _data;
1580e5c31af7Sopenharmony_ci}
1581e5c31af7Sopenharmony_ci
1582e5c31af7Sopenharmony_cichar* RandomArrayGenerator::generatePerQuad (int seed, int count, int componentCount, int stride, Array::Primitive primitive, Array::InputType type, GLValue min, GLValue max)
1583e5c31af7Sopenharmony_ci{
1584e5c31af7Sopenharmony_ci	char* data = DE_NULL;
1585e5c31af7Sopenharmony_ci
1586e5c31af7Sopenharmony_ci	switch (type)
1587e5c31af7Sopenharmony_ci	{
1588e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FLOAT:
1589e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Float>(seed, count, componentCount, stride, primitive, min.fl, max.fl);
1590e5c31af7Sopenharmony_ci			break;
1591e5c31af7Sopenharmony_ci
1592e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_FIXED:
1593e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Fixed>(seed, count, componentCount, stride, primitive, min.fi, max.fi);
1594e5c31af7Sopenharmony_ci			break;
1595e5c31af7Sopenharmony_ci
1596e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_DOUBLE:
1597e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Double>(seed, count, componentCount, stride, primitive, min.d, max.d);
1598e5c31af7Sopenharmony_ci			break;
1599e5c31af7Sopenharmony_ci
1600e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_BYTE:
1601e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Byte>(seed, count, componentCount, stride, primitive, min.b, max.b);
1602e5c31af7Sopenharmony_ci			break;
1603e5c31af7Sopenharmony_ci
1604e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_SHORT:
1605e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Short>(seed, count, componentCount, stride, primitive, min.s, max.s);
1606e5c31af7Sopenharmony_ci			break;
1607e5c31af7Sopenharmony_ci
1608e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_BYTE:
1609e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Ubyte>(seed, count, componentCount, stride, primitive, min.ub, max.ub);
1610e5c31af7Sopenharmony_ci			break;
1611e5c31af7Sopenharmony_ci
1612e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_SHORT:
1613e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Ushort>(seed, count, componentCount, stride, primitive, min.us, max.us);
1614e5c31af7Sopenharmony_ci			break;
1615e5c31af7Sopenharmony_ci
1616e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_UNSIGNED_INT:
1617e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Uint>(seed, count, componentCount, stride, primitive, min.ui, max.ui);
1618e5c31af7Sopenharmony_ci			break;
1619e5c31af7Sopenharmony_ci
1620e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_INT:
1621e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Int>(seed, count, componentCount, stride, primitive, min.i, max.i);
1622e5c31af7Sopenharmony_ci			break;
1623e5c31af7Sopenharmony_ci
1624e5c31af7Sopenharmony_ci		case Array::INPUTTYPE_HALF:
1625e5c31af7Sopenharmony_ci			data = createPerQuads<GLValue::Half>(seed, count, componentCount, stride, primitive, min.h, max.h);
1626e5c31af7Sopenharmony_ci			break;
1627e5c31af7Sopenharmony_ci
1628e5c31af7Sopenharmony_ci		default:
1629e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1630e5c31af7Sopenharmony_ci			break;
1631e5c31af7Sopenharmony_ci	}
1632e5c31af7Sopenharmony_ci
1633e5c31af7Sopenharmony_ci	return data;
1634e5c31af7Sopenharmony_ci}
1635e5c31af7Sopenharmony_ci
1636e5c31af7Sopenharmony_citemplate<typename T>
1637e5c31af7Sopenharmony_cichar* RandomArrayGenerator::createPerQuads (int seed, int count, int componentCount, int stride, Array::Primitive primitive, T min, T max)
1638e5c31af7Sopenharmony_ci{
1639e5c31af7Sopenharmony_ci	deRandom rnd;
1640e5c31af7Sopenharmony_ci	deRandom_init(&rnd, seed);
1641e5c31af7Sopenharmony_ci
1642e5c31af7Sopenharmony_ci	int componentStride = sizeof(T);
1643e5c31af7Sopenharmony_ci
1644e5c31af7Sopenharmony_ci	if (stride == 0)
1645e5c31af7Sopenharmony_ci		stride = componentStride * componentCount;
1646e5c31af7Sopenharmony_ci
1647e5c31af7Sopenharmony_ci	int quadStride = 0;
1648e5c31af7Sopenharmony_ci
1649e5c31af7Sopenharmony_ci	switch (primitive)
1650e5c31af7Sopenharmony_ci	{
1651e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_TRIANGLES:
1652e5c31af7Sopenharmony_ci			quadStride = stride * 6;
1653e5c31af7Sopenharmony_ci			break;
1654e5c31af7Sopenharmony_ci
1655e5c31af7Sopenharmony_ci		default:
1656e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1657e5c31af7Sopenharmony_ci			break;
1658e5c31af7Sopenharmony_ci	}
1659e5c31af7Sopenharmony_ci
1660e5c31af7Sopenharmony_ci	char* data = new char[count * quadStride];
1661e5c31af7Sopenharmony_ci
1662e5c31af7Sopenharmony_ci	for (int quadNdx = 0; quadNdx < count; quadNdx++)
1663e5c31af7Sopenharmony_ci	{
1664e5c31af7Sopenharmony_ci		for (int componentNdx = 0; componentNdx < componentCount; componentNdx++)
1665e5c31af7Sopenharmony_ci		{
1666e5c31af7Sopenharmony_ci			T val = getRandom<T>(rnd, min, max);
1667e5c31af7Sopenharmony_ci
1668e5c31af7Sopenharmony_ci			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 0 + componentStride * componentNdx, val);
1669e5c31af7Sopenharmony_ci			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 1 + componentStride * componentNdx, val);
1670e5c31af7Sopenharmony_ci			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 2 + componentStride * componentNdx, val);
1671e5c31af7Sopenharmony_ci			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 3 + componentStride * componentNdx, val);
1672e5c31af7Sopenharmony_ci			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 4 + componentStride * componentNdx, val);
1673e5c31af7Sopenharmony_ci			alignmentSafeAssignment<T>(data + quadNdx * quadStride + stride * 5 + componentStride * componentNdx, val);
1674e5c31af7Sopenharmony_ci		}
1675e5c31af7Sopenharmony_ci	}
1676e5c31af7Sopenharmony_ci
1677e5c31af7Sopenharmony_ci	return data;
1678e5c31af7Sopenharmony_ci}
1679e5c31af7Sopenharmony_ci
1680e5c31af7Sopenharmony_ci// VertexArrayTest
1681e5c31af7Sopenharmony_ci
1682e5c31af7Sopenharmony_ciVertexArrayTest::VertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name ,const char* desc)
1683e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, desc)
1684e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
1685e5c31af7Sopenharmony_ci	, m_refBuffers		(DE_NULL)
1686e5c31af7Sopenharmony_ci	, m_refContext		(DE_NULL)
1687e5c31af7Sopenharmony_ci	, m_glesContext		(DE_NULL)
1688e5c31af7Sopenharmony_ci	, m_glArrayPack		(DE_NULL)
1689e5c31af7Sopenharmony_ci	, m_rrArrayPack		(DE_NULL)
1690e5c31af7Sopenharmony_ci	, m_isOk			(false)
1691e5c31af7Sopenharmony_ci	, m_maxDiffRed		(deCeilFloatToInt32(256.0f * (2.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().redBits))))
1692e5c31af7Sopenharmony_ci	, m_maxDiffGreen	(deCeilFloatToInt32(256.0f * (2.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().greenBits))))
1693e5c31af7Sopenharmony_ci	, m_maxDiffBlue		(deCeilFloatToInt32(256.0f * (2.0f / (float)(1 << m_renderCtx.getRenderTarget().getPixelFormat().blueBits))))
1694e5c31af7Sopenharmony_ci{
1695e5c31af7Sopenharmony_ci}
1696e5c31af7Sopenharmony_ci
1697e5c31af7Sopenharmony_ciVertexArrayTest::~VertexArrayTest (void)
1698e5c31af7Sopenharmony_ci{
1699e5c31af7Sopenharmony_ci	deinit();
1700e5c31af7Sopenharmony_ci}
1701e5c31af7Sopenharmony_ci
1702e5c31af7Sopenharmony_civoid VertexArrayTest::init (void)
1703e5c31af7Sopenharmony_ci{
1704e5c31af7Sopenharmony_ci	const int						renderTargetWidth	= de::min(512, m_renderCtx.getRenderTarget().getWidth());
1705e5c31af7Sopenharmony_ci	const int						renderTargetHeight	= de::min(512, m_renderCtx.getRenderTarget().getHeight());
1706e5c31af7Sopenharmony_ci	sglr::ReferenceContextLimits	limits				(m_renderCtx);
1707e5c31af7Sopenharmony_ci
1708e5c31af7Sopenharmony_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));
1709e5c31af7Sopenharmony_ci
1710e5c31af7Sopenharmony_ci	m_refBuffers		= new sglr::ReferenceContextBuffers(m_renderCtx.getRenderTarget().getPixelFormat(), 0, 0, renderTargetWidth, renderTargetHeight);
1711e5c31af7Sopenharmony_ci	m_refContext		= new sglr::ReferenceContext(limits, m_refBuffers->getColorbuffer(), m_refBuffers->getDepthbuffer(), m_refBuffers->getStencilbuffer());
1712e5c31af7Sopenharmony_ci
1713e5c31af7Sopenharmony_ci	m_glArrayPack		= new ContextArrayPack(m_renderCtx, *m_glesContext);
1714e5c31af7Sopenharmony_ci	m_rrArrayPack		= new ContextArrayPack(m_renderCtx, *m_refContext);
1715e5c31af7Sopenharmony_ci}
1716e5c31af7Sopenharmony_ci
1717e5c31af7Sopenharmony_civoid VertexArrayTest::deinit (void)
1718e5c31af7Sopenharmony_ci{
1719e5c31af7Sopenharmony_ci	delete m_glArrayPack;
1720e5c31af7Sopenharmony_ci	delete m_rrArrayPack;
1721e5c31af7Sopenharmony_ci	delete m_refBuffers;
1722e5c31af7Sopenharmony_ci	delete m_refContext;
1723e5c31af7Sopenharmony_ci	delete m_glesContext;
1724e5c31af7Sopenharmony_ci
1725e5c31af7Sopenharmony_ci	m_glArrayPack	= DE_NULL;
1726e5c31af7Sopenharmony_ci	m_rrArrayPack	= DE_NULL;
1727e5c31af7Sopenharmony_ci	m_refBuffers	= DE_NULL;
1728e5c31af7Sopenharmony_ci	m_refContext	= DE_NULL;
1729e5c31af7Sopenharmony_ci	m_glesContext	= DE_NULL;
1730e5c31af7Sopenharmony_ci}
1731e5c31af7Sopenharmony_ci
1732e5c31af7Sopenharmony_civoid VertexArrayTest::compare (void)
1733e5c31af7Sopenharmony_ci{
1734e5c31af7Sopenharmony_ci	const tcu::Surface&	ref		= m_rrArrayPack->getSurface();
1735e5c31af7Sopenharmony_ci	const tcu::Surface&	screen	= m_glArrayPack->getSurface();
1736e5c31af7Sopenharmony_ci
1737e5c31af7Sopenharmony_ci	if (m_renderCtx.getRenderTarget().getNumSamples() > 1)
1738e5c31af7Sopenharmony_ci	{
1739e5c31af7Sopenharmony_ci		// \todo [mika] Improve compare when using multisampling
1740e5c31af7Sopenharmony_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;
1741e5c31af7Sopenharmony_ci		m_isOk = tcu::fuzzyCompare(m_testCtx.getLog(), "Compare Results", "Compare Results", ref.getAccess(), screen.getAccess(), 1.5f, tcu::COMPARE_LOG_RESULT);
1742e5c31af7Sopenharmony_ci	}
1743e5c31af7Sopenharmony_ci	else
1744e5c31af7Sopenharmony_ci	{
1745e5c31af7Sopenharmony_ci		tcu::RGBA		threshold	(m_maxDiffRed, m_maxDiffGreen, m_maxDiffBlue, 255);
1746e5c31af7Sopenharmony_ci		tcu::Surface	error		(ref.getWidth(), ref.getHeight());
1747e5c31af7Sopenharmony_ci
1748e5c31af7Sopenharmony_ci		m_isOk = true;
1749e5c31af7Sopenharmony_ci
1750e5c31af7Sopenharmony_ci		for (int y = 0; y < ref.getHeight(); y++)
1751e5c31af7Sopenharmony_ci		{
1752e5c31af7Sopenharmony_ci			for (int x = 0; x < ref.getWidth(); x++)
1753e5c31af7Sopenharmony_ci			{
1754e5c31af7Sopenharmony_ci				tcu::RGBA	refPixel		= ref.getPixel(x, y);
1755e5c31af7Sopenharmony_ci				tcu::RGBA	screenPixel		= screen.getPixel(x, y);
1756e5c31af7Sopenharmony_ci				bool		isOkPixel		= false;
1757e5c31af7Sopenharmony_ci
1758e5c31af7Sopenharmony_ci				if (y == 0 || y + 1 == ref.getHeight() || x == 0 || x + 1 == ref.getWidth())
1759e5c31af7Sopenharmony_ci				{
1760e5c31af7Sopenharmony_ci					// Don't check borders since the pixel neighborhood is undefined
1761e5c31af7Sopenharmony_ci					error.setPixel(x, y, tcu::RGBA(screenPixel.getRed(), (screenPixel.getGreen() + 255) / 2, screenPixel.getBlue(), 255));
1762e5c31af7Sopenharmony_ci					continue;
1763e5c31af7Sopenharmony_ci				}
1764e5c31af7Sopenharmony_ci
1765e5c31af7Sopenharmony_ci				// Don't do comparisons for this pixel if it belongs to a one-pixel-thin part (i.e. it doesn't have similar-color neighbors in both x and y directions) in both result and reference.
1766e5c31af7Sopenharmony_ci				// This fixes some false negatives.
1767e5c31af7Sopenharmony_ci				bool		refThin			= (!tcu::compareThreshold(refPixel, ref.getPixel(x-1, y  ), threshold) && !tcu::compareThreshold(refPixel, ref.getPixel(x+1, y  ), threshold)) ||
1768e5c31af7Sopenharmony_ci											  (!tcu::compareThreshold(refPixel, ref.getPixel(x  , y-1), threshold) && !tcu::compareThreshold(refPixel, ref.getPixel(x  , y+1), threshold));
1769e5c31af7Sopenharmony_ci				bool		screenThin		= (!tcu::compareThreshold(screenPixel, screen.getPixel(x-1, y  ), threshold) && !tcu::compareThreshold(screenPixel, screen.getPixel(x+1, y  ), threshold)) ||
1770e5c31af7Sopenharmony_ci											  (!tcu::compareThreshold(screenPixel, screen.getPixel(x  , y-1), threshold) && !tcu::compareThreshold(screenPixel, screen.getPixel(x  , y+1), threshold));
1771e5c31af7Sopenharmony_ci
1772e5c31af7Sopenharmony_ci				if (refThin && screenThin)
1773e5c31af7Sopenharmony_ci					isOkPixel = true;
1774e5c31af7Sopenharmony_ci				else
1775e5c31af7Sopenharmony_ci				{
1776e5c31af7Sopenharmony_ci					for (int dy = -1; dy < 2 && !isOkPixel; dy++)
1777e5c31af7Sopenharmony_ci					{
1778e5c31af7Sopenharmony_ci						for (int dx = -1; dx < 2 && !isOkPixel; dx++)
1779e5c31af7Sopenharmony_ci						{
1780e5c31af7Sopenharmony_ci							// Check reference pixel against screen pixel
1781e5c31af7Sopenharmony_ci							{
1782e5c31af7Sopenharmony_ci								tcu::RGBA	screenCmpPixel	= screen.getPixel(x+dx, y+dy);
1783e5c31af7Sopenharmony_ci								deUint8		r				= (deUint8)deAbs32(refPixel.getRed()	- screenCmpPixel.getRed());
1784e5c31af7Sopenharmony_ci								deUint8		g				= (deUint8)deAbs32(refPixel.getGreen()	- screenCmpPixel.getGreen());
1785e5c31af7Sopenharmony_ci								deUint8		b				= (deUint8)deAbs32(refPixel.getBlue()	- screenCmpPixel.getBlue());
1786e5c31af7Sopenharmony_ci
1787e5c31af7Sopenharmony_ci								if (r <= m_maxDiffRed && g <= m_maxDiffGreen && b <= m_maxDiffBlue)
1788e5c31af7Sopenharmony_ci									isOkPixel = true;
1789e5c31af7Sopenharmony_ci							}
1790e5c31af7Sopenharmony_ci
1791e5c31af7Sopenharmony_ci							// Check screen pixels against reference pixel
1792e5c31af7Sopenharmony_ci							{
1793e5c31af7Sopenharmony_ci								tcu::RGBA	refCmpPixel		= ref.getPixel(x+dx, y+dy);
1794e5c31af7Sopenharmony_ci								deUint8		r				= (deUint8)deAbs32(refCmpPixel.getRed()		- screenPixel.getRed());
1795e5c31af7Sopenharmony_ci								deUint8		g				= (deUint8)deAbs32(refCmpPixel.getGreen()	- screenPixel.getGreen());
1796e5c31af7Sopenharmony_ci								deUint8		b				= (deUint8)deAbs32(refCmpPixel.getBlue()	- screenPixel.getBlue());
1797e5c31af7Sopenharmony_ci
1798e5c31af7Sopenharmony_ci								if (r <= m_maxDiffRed && g <= m_maxDiffGreen && b <= m_maxDiffBlue)
1799e5c31af7Sopenharmony_ci									isOkPixel = true;
1800e5c31af7Sopenharmony_ci							}
1801e5c31af7Sopenharmony_ci						}
1802e5c31af7Sopenharmony_ci					}
1803e5c31af7Sopenharmony_ci				}
1804e5c31af7Sopenharmony_ci
1805e5c31af7Sopenharmony_ci				if (isOkPixel)
1806e5c31af7Sopenharmony_ci					error.setPixel(x, y, tcu::RGBA(screen.getPixel(x, y).getRed(), (screen.getPixel(x, y).getGreen() + 255) / 2, screen.getPixel(x, y).getBlue(), 255));
1807e5c31af7Sopenharmony_ci				else
1808e5c31af7Sopenharmony_ci				{
1809e5c31af7Sopenharmony_ci					error.setPixel(x, y, tcu::RGBA(255, 0, 0, 255));
1810e5c31af7Sopenharmony_ci					m_isOk = false;
1811e5c31af7Sopenharmony_ci				}
1812e5c31af7Sopenharmony_ci			}
1813e5c31af7Sopenharmony_ci		}
1814e5c31af7Sopenharmony_ci
1815e5c31af7Sopenharmony_ci		tcu::TestLog& log = m_testCtx.getLog();
1816e5c31af7Sopenharmony_ci		if (!m_isOk)
1817e5c31af7Sopenharmony_ci		{
1818e5c31af7Sopenharmony_ci			log << TestLog::Message << "Image comparison failed, threshold = (" << m_maxDiffRed << ", " << m_maxDiffGreen << ", " << m_maxDiffBlue << ")" << TestLog::EndMessage;
1819e5c31af7Sopenharmony_ci			log << TestLog::ImageSet("Compare result", "Result of rendering")
1820e5c31af7Sopenharmony_ci				<< TestLog::Image("Result",		"Result",		screen)
1821e5c31af7Sopenharmony_ci				<< TestLog::Image("Reference",	"Reference",	ref)
1822e5c31af7Sopenharmony_ci				<< TestLog::Image("ErrorMask",	"Error mask",	error)
1823e5c31af7Sopenharmony_ci				<< TestLog::EndImageSet;
1824e5c31af7Sopenharmony_ci		}
1825e5c31af7Sopenharmony_ci		else
1826e5c31af7Sopenharmony_ci		{
1827e5c31af7Sopenharmony_ci			log << TestLog::ImageSet("Compare result", "Result of rendering")
1828e5c31af7Sopenharmony_ci				<< TestLog::Image("Result", "Result", screen)
1829e5c31af7Sopenharmony_ci				<< TestLog::EndImageSet;
1830e5c31af7Sopenharmony_ci		}
1831e5c31af7Sopenharmony_ci	}
1832e5c31af7Sopenharmony_ci}
1833e5c31af7Sopenharmony_ci
1834e5c31af7Sopenharmony_ci// MultiVertexArrayTest
1835e5c31af7Sopenharmony_ci
1836e5c31af7Sopenharmony_ciMultiVertexArrayTest::Spec::ArraySpec::ArraySpec(Array::InputType inputType_, Array::OutputType outputType_, Array::Storage storage_, Array::Usage usage_, int componentCount_, int offset_, int stride_, bool normalize_, GLValue min_, GLValue max_)
1837e5c31af7Sopenharmony_ci	: inputType		(inputType_)
1838e5c31af7Sopenharmony_ci	, outputType	(outputType_)
1839e5c31af7Sopenharmony_ci	, storage		(storage_)
1840e5c31af7Sopenharmony_ci	, usage			(usage_)
1841e5c31af7Sopenharmony_ci	, componentCount(componentCount_)
1842e5c31af7Sopenharmony_ci	, offset		(offset_)
1843e5c31af7Sopenharmony_ci	, stride		(stride_)
1844e5c31af7Sopenharmony_ci	, normalize		(normalize_)
1845e5c31af7Sopenharmony_ci	, min			(min_)
1846e5c31af7Sopenharmony_ci	, max			(max_)
1847e5c31af7Sopenharmony_ci{
1848e5c31af7Sopenharmony_ci}
1849e5c31af7Sopenharmony_ci
1850e5c31af7Sopenharmony_cistd::string MultiVertexArrayTest::Spec::getName (void) const
1851e5c31af7Sopenharmony_ci{
1852e5c31af7Sopenharmony_ci	std::stringstream name;
1853e5c31af7Sopenharmony_ci
1854e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < arrays.size(); ++ndx)
1855e5c31af7Sopenharmony_ci	{
1856e5c31af7Sopenharmony_ci		const ArraySpec& array = arrays[ndx];
1857e5c31af7Sopenharmony_ci
1858e5c31af7Sopenharmony_ci		if (arrays.size() > 1)
1859e5c31af7Sopenharmony_ci			name << "array" << ndx << "_";
1860e5c31af7Sopenharmony_ci
1861e5c31af7Sopenharmony_ci		name
1862e5c31af7Sopenharmony_ci			<< Array::storageToString(array.storage) << "_"
1863e5c31af7Sopenharmony_ci			<< array.offset << "_"
1864e5c31af7Sopenharmony_ci			<< array.stride << "_"
1865e5c31af7Sopenharmony_ci			<< Array::inputTypeToString((Array::InputType)array.inputType);
1866e5c31af7Sopenharmony_ci		if (array.inputType != Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 && array.inputType != Array::INPUTTYPE_INT_2_10_10_10)
1867e5c31af7Sopenharmony_ci			name << array.componentCount;
1868e5c31af7Sopenharmony_ci		name
1869e5c31af7Sopenharmony_ci			<< "_"
1870e5c31af7Sopenharmony_ci			<< (array.normalize ? "normalized_" : "")
1871e5c31af7Sopenharmony_ci			<< Array::outputTypeToString(array.outputType) << "_"
1872e5c31af7Sopenharmony_ci			<< Array::usageTypeToString(array.usage) << "_";
1873e5c31af7Sopenharmony_ci	}
1874e5c31af7Sopenharmony_ci
1875e5c31af7Sopenharmony_ci	if (first)
1876e5c31af7Sopenharmony_ci		name << "first" << first << "_";
1877e5c31af7Sopenharmony_ci
1878e5c31af7Sopenharmony_ci	switch (primitive)
1879e5c31af7Sopenharmony_ci	{
1880e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_TRIANGLES:
1881e5c31af7Sopenharmony_ci			name << "quads_";
1882e5c31af7Sopenharmony_ci			break;
1883e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_POINTS:
1884e5c31af7Sopenharmony_ci			name << "points_";
1885e5c31af7Sopenharmony_ci			break;
1886e5c31af7Sopenharmony_ci
1887e5c31af7Sopenharmony_ci		default:
1888e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1889e5c31af7Sopenharmony_ci			break;
1890e5c31af7Sopenharmony_ci	}
1891e5c31af7Sopenharmony_ci
1892e5c31af7Sopenharmony_ci	name << drawCount;
1893e5c31af7Sopenharmony_ci
1894e5c31af7Sopenharmony_ci	return name.str();
1895e5c31af7Sopenharmony_ci}
1896e5c31af7Sopenharmony_ci
1897e5c31af7Sopenharmony_cistd::string MultiVertexArrayTest::Spec::getDesc (void) const
1898e5c31af7Sopenharmony_ci{
1899e5c31af7Sopenharmony_ci	std::stringstream desc;
1900e5c31af7Sopenharmony_ci
1901e5c31af7Sopenharmony_ci	for (size_t ndx = 0; ndx < arrays.size(); ++ndx)
1902e5c31af7Sopenharmony_ci	{
1903e5c31af7Sopenharmony_ci		const ArraySpec& array = arrays[ndx];
1904e5c31af7Sopenharmony_ci
1905e5c31af7Sopenharmony_ci		desc
1906e5c31af7Sopenharmony_ci			<< "Array " << ndx << ": "
1907e5c31af7Sopenharmony_ci			<< "Storage in " << Array::storageToString(array.storage) << ", "
1908e5c31af7Sopenharmony_ci			<< "stride " << array.stride << ", "
1909e5c31af7Sopenharmony_ci			<< "input datatype " << Array::inputTypeToString((Array::InputType)array.inputType) << ", "
1910e5c31af7Sopenharmony_ci			<< "input component count " << array.componentCount << ", "
1911e5c31af7Sopenharmony_ci			<< (array.normalize ? "normalized, " : "")
1912e5c31af7Sopenharmony_ci			<< "used as " << Array::outputTypeToString(array.outputType) << ", ";
1913e5c31af7Sopenharmony_ci	}
1914e5c31af7Sopenharmony_ci
1915e5c31af7Sopenharmony_ci	desc
1916e5c31af7Sopenharmony_ci		<< "drawArrays(), "
1917e5c31af7Sopenharmony_ci		<< "first " << first << ", "
1918e5c31af7Sopenharmony_ci		<< drawCount;
1919e5c31af7Sopenharmony_ci
1920e5c31af7Sopenharmony_ci	switch (primitive)
1921e5c31af7Sopenharmony_ci	{
1922e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_TRIANGLES:
1923e5c31af7Sopenharmony_ci			desc << "quads ";
1924e5c31af7Sopenharmony_ci			break;
1925e5c31af7Sopenharmony_ci		case Array::PRIMITIVE_POINTS:
1926e5c31af7Sopenharmony_ci			desc << "points";
1927e5c31af7Sopenharmony_ci			break;
1928e5c31af7Sopenharmony_ci
1929e5c31af7Sopenharmony_ci		default:
1930e5c31af7Sopenharmony_ci			DE_ASSERT(false);
1931e5c31af7Sopenharmony_ci			break;
1932e5c31af7Sopenharmony_ci	}
1933e5c31af7Sopenharmony_ci
1934e5c31af7Sopenharmony_ci
1935e5c31af7Sopenharmony_ci	return desc.str();
1936e5c31af7Sopenharmony_ci}
1937e5c31af7Sopenharmony_ci
1938e5c31af7Sopenharmony_ciMultiVertexArrayTest::MultiVertexArrayTest (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const Spec& spec, const char* name, const char* desc)
1939e5c31af7Sopenharmony_ci	: VertexArrayTest	(testCtx, renderCtx, name, desc)
1940e5c31af7Sopenharmony_ci	, m_spec			(spec)
1941e5c31af7Sopenharmony_ci	, m_iteration		(0)
1942e5c31af7Sopenharmony_ci{
1943e5c31af7Sopenharmony_ci}
1944e5c31af7Sopenharmony_ci
1945e5c31af7Sopenharmony_ciMultiVertexArrayTest::~MultiVertexArrayTest	(void)
1946e5c31af7Sopenharmony_ci{
1947e5c31af7Sopenharmony_ci}
1948e5c31af7Sopenharmony_ci
1949e5c31af7Sopenharmony_ciMultiVertexArrayTest::IterateResult MultiVertexArrayTest::iterate (void)
1950e5c31af7Sopenharmony_ci{
1951e5c31af7Sopenharmony_ci	if (m_iteration == 0)
1952e5c31af7Sopenharmony_ci	{
1953e5c31af7Sopenharmony_ci		const size_t	primitiveSize		= (m_spec.primitive == Array::PRIMITIVE_TRIANGLES) ? (6) : (1); // in non-indexed draw Triangles means rectangles
1954e5c31af7Sopenharmony_ci		float			coordScale			= 1.0f;
1955e5c31af7Sopenharmony_ci		float			colorScale			= 1.0f;
1956e5c31af7Sopenharmony_ci		const bool		useVao				= m_renderCtx.getType().getProfile() == glu::PROFILE_CORE;
1957e5c31af7Sopenharmony_ci
1958e5c31af7Sopenharmony_ci		// Log info
1959e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::Message << m_spec.getDesc() << TestLog::EndMessage;
1960e5c31af7Sopenharmony_ci
1961e5c31af7Sopenharmony_ci		// Color and Coord scale
1962e5c31af7Sopenharmony_ci		{
1963e5c31af7Sopenharmony_ci			// First array is always position
1964e5c31af7Sopenharmony_ci			{
1965e5c31af7Sopenharmony_ci				Spec::ArraySpec arraySpec = m_spec.arrays[0];
1966e5c31af7Sopenharmony_ci				if (arraySpec.inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10)
1967e5c31af7Sopenharmony_ci				{
1968e5c31af7Sopenharmony_ci					if (arraySpec.normalize)
1969e5c31af7Sopenharmony_ci						coordScale = 1.0f;
1970e5c31af7Sopenharmony_ci					else
1971e5c31af7Sopenharmony_ci						coordScale = 1.0 / 1024.0;
1972e5c31af7Sopenharmony_ci				}
1973e5c31af7Sopenharmony_ci				else if (arraySpec.inputType == Array::INPUTTYPE_INT_2_10_10_10)
1974e5c31af7Sopenharmony_ci				{
1975e5c31af7Sopenharmony_ci					if (arraySpec.normalize)
1976e5c31af7Sopenharmony_ci						coordScale = 1.0f;
1977e5c31af7Sopenharmony_ci					else
1978e5c31af7Sopenharmony_ci						coordScale = 1.0 / 512.0;
1979e5c31af7Sopenharmony_ci				}
1980e5c31af7Sopenharmony_ci				else
1981e5c31af7Sopenharmony_ci					coordScale = (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(0.9 / double(arraySpec.max.toFloat())));
1982e5c31af7Sopenharmony_ci
1983e5c31af7Sopenharmony_ci				if (arraySpec.outputType == Array::OUTPUTTYPE_VEC3 || arraySpec.outputType == Array::OUTPUTTYPE_VEC4
1984e5c31af7Sopenharmony_ci					|| arraySpec.outputType == Array::OUTPUTTYPE_IVEC3 || arraySpec.outputType == Array::OUTPUTTYPE_IVEC4
1985e5c31af7Sopenharmony_ci					|| arraySpec.outputType == Array::OUTPUTTYPE_UVEC3 || arraySpec.outputType == Array::OUTPUTTYPE_UVEC4)
1986e5c31af7Sopenharmony_ci						coordScale = coordScale * 0.5f;
1987e5c31af7Sopenharmony_ci			}
1988e5c31af7Sopenharmony_ci
1989e5c31af7Sopenharmony_ci			// And other arrays are color-like
1990e5c31af7Sopenharmony_ci			for (int arrayNdx = 1; arrayNdx < (int)m_spec.arrays.size(); arrayNdx++)
1991e5c31af7Sopenharmony_ci			{
1992e5c31af7Sopenharmony_ci				Spec::ArraySpec arraySpec	= m_spec.arrays[arrayNdx];
1993e5c31af7Sopenharmony_ci
1994e5c31af7Sopenharmony_ci				colorScale *= (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(1.0 / double(arraySpec.max.toFloat())));
1995e5c31af7Sopenharmony_ci				if (arraySpec.outputType == Array::OUTPUTTYPE_VEC4)
1996e5c31af7Sopenharmony_ci					colorScale *= (arraySpec.normalize && !inputTypeIsFloatType(arraySpec.inputType) ? 1.0f : float(1.0 / double(arraySpec.max.toFloat())));
1997e5c31af7Sopenharmony_ci			}
1998e5c31af7Sopenharmony_ci		}
1999e5c31af7Sopenharmony_ci
2000e5c31af7Sopenharmony_ci		// Data
2001e5c31af7Sopenharmony_ci		for (int arrayNdx = 0; arrayNdx < (int)m_spec.arrays.size(); arrayNdx++)
2002e5c31af7Sopenharmony_ci		{
2003e5c31af7Sopenharmony_ci			Spec::ArraySpec arraySpec		= m_spec.arrays[arrayNdx];
2004e5c31af7Sopenharmony_ci			const int		seed			= int(arraySpec.inputType) + 10 * int(arraySpec.outputType) + 100 * int(arraySpec.storage) + 1000 * int(m_spec.primitive) + 10000 * int(arraySpec.usage) + int(m_spec.drawCount) + 12 * int(arraySpec.componentCount) + int(arraySpec.stride) + int(arraySpec.normalize);
2005e5c31af7Sopenharmony_ci			const char*		data			= DE_NULL;
2006e5c31af7Sopenharmony_ci			const size_t	stride			= (arraySpec.stride == 0) ? (arraySpec.componentCount * Array::inputTypeSize(arraySpec.inputType)) : (arraySpec.stride);
2007e5c31af7Sopenharmony_ci			const size_t	bufferSize		= arraySpec.offset + stride * (m_spec.drawCount * primitiveSize - 1) + arraySpec.componentCount  * Array::inputTypeSize(arraySpec.inputType);
2008e5c31af7Sopenharmony_ci			// Snap values to at least 3x3 grid
2009e5c31af7Sopenharmony_ci			const float		gridSize		= 3.0f / (float)(de::min(m_renderCtx.getRenderTarget().getWidth(), m_renderCtx.getRenderTarget().getHeight()) - 1);
2010e5c31af7Sopenharmony_ci
2011e5c31af7Sopenharmony_ci			switch (m_spec.primitive)
2012e5c31af7Sopenharmony_ci			{
2013e5c31af7Sopenharmony_ci	//			case Array::PRIMITIVE_POINTS:
2014e5c31af7Sopenharmony_ci	//				data = RandomArrayGenerator::generateArray(seed, arraySpec.min, arraySpec.max, arraySpec.count, arraySpec.componentCount, arraySpec.stride, arraySpec.inputType);
2015e5c31af7Sopenharmony_ci	//				break;
2016e5c31af7Sopenharmony_ci				case Array::PRIMITIVE_TRIANGLES:
2017e5c31af7Sopenharmony_ci					if (arrayNdx == 0)
2018e5c31af7Sopenharmony_ci					{
2019e5c31af7Sopenharmony_ci						data = RandomArrayGenerator::generateQuads(seed, m_spec.drawCount, arraySpec.componentCount, arraySpec.offset, arraySpec.stride, m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max, gridSize);
2020e5c31af7Sopenharmony_ci					}
2021e5c31af7Sopenharmony_ci					else
2022e5c31af7Sopenharmony_ci					{
2023e5c31af7Sopenharmony_ci						DE_ASSERT(arraySpec.offset == 0); // \note [jarkko] it just hasn't been implemented
2024e5c31af7Sopenharmony_ci						data = RandomArrayGenerator::generatePerQuad(seed, m_spec.drawCount, arraySpec.componentCount, arraySpec.stride, m_spec.primitive, arraySpec.inputType, arraySpec.min, arraySpec.max);
2025e5c31af7Sopenharmony_ci					}
2026e5c31af7Sopenharmony_ci					break;
2027e5c31af7Sopenharmony_ci
2028e5c31af7Sopenharmony_ci				default:
2029e5c31af7Sopenharmony_ci					DE_ASSERT(false);
2030e5c31af7Sopenharmony_ci					break;
2031e5c31af7Sopenharmony_ci			}
2032e5c31af7Sopenharmony_ci
2033e5c31af7Sopenharmony_ci			m_glArrayPack->newArray(arraySpec.storage);
2034e5c31af7Sopenharmony_ci			m_rrArrayPack->newArray(arraySpec.storage);
2035e5c31af7Sopenharmony_ci
2036e5c31af7Sopenharmony_ci			m_glArrayPack->getArray(arrayNdx)->data(Array::TARGET_ARRAY, (int)bufferSize, data, arraySpec.usage);
2037e5c31af7Sopenharmony_ci			m_rrArrayPack->getArray(arrayNdx)->data(Array::TARGET_ARRAY, (int)bufferSize, data, arraySpec.usage);
2038e5c31af7Sopenharmony_ci
2039e5c31af7Sopenharmony_ci			m_glArrayPack->getArray(arrayNdx)->bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
2040e5c31af7Sopenharmony_ci			m_rrArrayPack->getArray(arrayNdx)->bind(arrayNdx, arraySpec.offset, arraySpec.componentCount, arraySpec.inputType, arraySpec.outputType, arraySpec.normalize, arraySpec.stride);
2041e5c31af7Sopenharmony_ci
2042e5c31af7Sopenharmony_ci			delete [] data;
2043e5c31af7Sopenharmony_ci		}
2044e5c31af7Sopenharmony_ci
2045e5c31af7Sopenharmony_ci		try
2046e5c31af7Sopenharmony_ci		{
2047e5c31af7Sopenharmony_ci			m_glArrayPack->render(m_spec.primitive, m_spec.first, m_spec.drawCount * (int)primitiveSize, useVao, coordScale, colorScale);
2048e5c31af7Sopenharmony_ci			m_testCtx.touchWatchdog();
2049e5c31af7Sopenharmony_ci			m_rrArrayPack->render(m_spec.primitive, m_spec.first, m_spec.drawCount * (int)primitiveSize, useVao, coordScale, colorScale);
2050e5c31af7Sopenharmony_ci		}
2051e5c31af7Sopenharmony_ci		catch (glu::Error& err)
2052e5c31af7Sopenharmony_ci		{
2053e5c31af7Sopenharmony_ci			// GL Errors are ok if the mode is not properly aligned
2054e5c31af7Sopenharmony_ci
2055e5c31af7Sopenharmony_ci			m_testCtx.getLog() << TestLog::Message << "Got error: " << err.what() << TestLog::EndMessage;
2056e5c31af7Sopenharmony_ci
2057e5c31af7Sopenharmony_ci			if (isUnalignedBufferOffsetTest())
2058e5c31af7Sopenharmony_ci				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
2059e5c31af7Sopenharmony_ci			else if (isUnalignedBufferStrideTest())
2060e5c31af7Sopenharmony_ci				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
2061e5c31af7Sopenharmony_ci			else
2062e5c31af7Sopenharmony_ci				throw;
2063e5c31af7Sopenharmony_ci
2064e5c31af7Sopenharmony_ci			return STOP;
2065e5c31af7Sopenharmony_ci		}
2066e5c31af7Sopenharmony_ci
2067e5c31af7Sopenharmony_ci		m_iteration++;
2068e5c31af7Sopenharmony_ci		return CONTINUE;
2069e5c31af7Sopenharmony_ci	}
2070e5c31af7Sopenharmony_ci	else if (m_iteration == 1)
2071e5c31af7Sopenharmony_ci	{
2072e5c31af7Sopenharmony_ci		compare();
2073e5c31af7Sopenharmony_ci
2074e5c31af7Sopenharmony_ci		if (m_isOk)
2075e5c31af7Sopenharmony_ci		{
2076e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2077e5c31af7Sopenharmony_ci		}
2078e5c31af7Sopenharmony_ci		else
2079e5c31af7Sopenharmony_ci		{
2080e5c31af7Sopenharmony_ci			if (isUnalignedBufferOffsetTest())
2081e5c31af7Sopenharmony_ci				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned buffers.");
2082e5c31af7Sopenharmony_ci			else if (isUnalignedBufferStrideTest())
2083e5c31af7Sopenharmony_ci				m_testCtx.setTestResult(QP_TEST_RESULT_COMPATIBILITY_WARNING, "Failed to draw with unaligned stride.");
2084e5c31af7Sopenharmony_ci			else
2085e5c31af7Sopenharmony_ci				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed.");
2086e5c31af7Sopenharmony_ci		}
2087e5c31af7Sopenharmony_ci
2088e5c31af7Sopenharmony_ci		m_iteration++;
2089e5c31af7Sopenharmony_ci		return STOP;
2090e5c31af7Sopenharmony_ci	}
2091e5c31af7Sopenharmony_ci	else
2092e5c31af7Sopenharmony_ci	{
2093e5c31af7Sopenharmony_ci		DE_ASSERT(false);
2094e5c31af7Sopenharmony_ci		return STOP;
2095e5c31af7Sopenharmony_ci	}
2096e5c31af7Sopenharmony_ci}
2097e5c31af7Sopenharmony_ci
2098e5c31af7Sopenharmony_cibool MultiVertexArrayTest::isUnalignedBufferOffsetTest (void) const
2099e5c31af7Sopenharmony_ci{
2100e5c31af7Sopenharmony_ci	// Buffer offsets should be data type size aligned
2101e5c31af7Sopenharmony_ci	for (size_t i = 0; i < m_spec.arrays.size(); ++i)
2102e5c31af7Sopenharmony_ci	{
2103e5c31af7Sopenharmony_ci		if (m_spec.arrays[i].storage == Array::STORAGE_BUFFER)
2104e5c31af7Sopenharmony_ci		{
2105e5c31af7Sopenharmony_ci			const bool inputTypePacked = m_spec.arrays[i].inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_spec.arrays[i].inputType == Array::INPUTTYPE_INT_2_10_10_10;
2106e5c31af7Sopenharmony_ci
2107e5c31af7Sopenharmony_ci			int dataTypeSize = Array::inputTypeSize(m_spec.arrays[i].inputType);
2108e5c31af7Sopenharmony_ci			if (inputTypePacked)
2109e5c31af7Sopenharmony_ci				dataTypeSize = 4;
2110e5c31af7Sopenharmony_ci
2111e5c31af7Sopenharmony_ci			if (m_spec.arrays[i].offset % dataTypeSize != 0)
2112e5c31af7Sopenharmony_ci				return true;
2113e5c31af7Sopenharmony_ci		}
2114e5c31af7Sopenharmony_ci	}
2115e5c31af7Sopenharmony_ci
2116e5c31af7Sopenharmony_ci	return false;
2117e5c31af7Sopenharmony_ci}
2118e5c31af7Sopenharmony_ci
2119e5c31af7Sopenharmony_cibool MultiVertexArrayTest::isUnalignedBufferStrideTest (void) const
2120e5c31af7Sopenharmony_ci{
2121e5c31af7Sopenharmony_ci	// Buffer strides should be data type size aligned
2122e5c31af7Sopenharmony_ci	for (size_t i = 0; i < m_spec.arrays.size(); ++i)
2123e5c31af7Sopenharmony_ci	{
2124e5c31af7Sopenharmony_ci		if (m_spec.arrays[i].storage == Array::STORAGE_BUFFER)
2125e5c31af7Sopenharmony_ci		{
2126e5c31af7Sopenharmony_ci			const bool inputTypePacked = m_spec.arrays[i].inputType == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_spec.arrays[i].inputType == Array::INPUTTYPE_INT_2_10_10_10;
2127e5c31af7Sopenharmony_ci
2128e5c31af7Sopenharmony_ci			int dataTypeSize = Array::inputTypeSize(m_spec.arrays[i].inputType);
2129e5c31af7Sopenharmony_ci			if (inputTypePacked)
2130e5c31af7Sopenharmony_ci				dataTypeSize = 4;
2131e5c31af7Sopenharmony_ci
2132e5c31af7Sopenharmony_ci			if (m_spec.arrays[i].stride % dataTypeSize != 0)
2133e5c31af7Sopenharmony_ci				return true;
2134e5c31af7Sopenharmony_ci		}
2135e5c31af7Sopenharmony_ci	}
2136e5c31af7Sopenharmony_ci
2137e5c31af7Sopenharmony_ci	return false;
2138e5c31af7Sopenharmony_ci}
2139e5c31af7Sopenharmony_ci
2140e5c31af7Sopenharmony_ci} // gls
2141e5c31af7Sopenharmony_ci} // deqp
2142