1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Vertex array and buffer tests
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fVertexArrayTest.hpp"
25#include "glsVertexArrayTests.hpp"
26
27#include <sstream>
28
29using namespace deqp::gls;
30
31namespace deqp
32{
33namespace gles3
34{
35namespace Functional
36{
37
38class SingleVertexArrayUsageGroup : public TestCaseGroup
39{
40public:
41									SingleVertexArrayUsageGroup		(Context& context, Array::Usage usage);
42	virtual							~SingleVertexArrayUsageGroup	(void);
43
44	virtual void					init							(void);
45
46private:
47									SingleVertexArrayUsageGroup		(const SingleVertexArrayUsageGroup& other);
48	SingleVertexArrayUsageGroup&	operator=						(const SingleVertexArrayUsageGroup& other);
49
50	Array::Usage					m_usage;
51};
52
53SingleVertexArrayUsageGroup::SingleVertexArrayUsageGroup (Context& context, Array::Usage usage)
54	: TestCaseGroup	(context, Array::usageTypeToString(usage).c_str(), Array::usageTypeToString(usage).c_str())
55	, m_usage		(usage)
56{
57}
58
59SingleVertexArrayUsageGroup::~SingleVertexArrayUsageGroup (void)
60{
61}
62
63template<class T>
64static std::string typeToString (T t)
65{
66	std::stringstream strm;
67	strm << t;
68	return strm.str();
69}
70
71void SingleVertexArrayUsageGroup::init (void)
72{
73	int					counts[]		= {1, 256};
74	int					strides[]		= {0, -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
75	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE};
76
77	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
78	{
79		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
80		{
81			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
82			{
83				const int			stride	= (strides[strideNdx] < 0 ? Array::inputTypeSize(inputTypes[inputTypeNdx]) * 2 : strides[strideNdx]);
84				const bool			aligned	= (stride % Array::inputTypeSize(inputTypes[inputTypeNdx])) == 0;
85				const std::string	name	= "stride" + typeToString(stride) + "_" + Array::inputTypeToString(inputTypes[inputTypeNdx]) + "_quads" + typeToString(counts[countNdx]);
86
87				MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
88																Array::OUTPUTTYPE_VEC2,
89																Array::STORAGE_BUFFER,
90																m_usage,
91																2,
92																0,
93																stride,
94																false,
95																GLValue::getMinValue(inputTypes[inputTypeNdx]),
96																GLValue::getMaxValue(inputTypes[inputTypeNdx]));
97
98				MultiVertexArrayTest::Spec spec;
99				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
100				spec.drawCount	= counts[countNdx];
101				spec.first		= 0;
102				spec.arrays.push_back(arraySpec);
103
104				if (aligned)
105					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
106			}
107		}
108	}
109}
110
111class SingleVertexArrayUsageTests : public TestCaseGroup
112{
113public:
114									SingleVertexArrayUsageTests		(Context& context);
115	virtual							~SingleVertexArrayUsageTests	(void);
116
117	virtual void					init							(void);
118
119private:
120									SingleVertexArrayUsageTests		(const SingleVertexArrayUsageTests& other);
121	SingleVertexArrayUsageTests&	operator=						(const SingleVertexArrayUsageTests& other);
122};
123
124SingleVertexArrayUsageTests::SingleVertexArrayUsageTests (Context& context)
125	: TestCaseGroup(context, "usages", "Single vertex atribute, usage")
126{
127}
128
129SingleVertexArrayUsageTests::~SingleVertexArrayUsageTests (void)
130{
131}
132
133void SingleVertexArrayUsageTests::init (void)
134{
135	// Test usage
136	Array::Usage		usages[]		= { Array::USAGE_STATIC_DRAW, Array::USAGE_STREAM_DRAW, Array::USAGE_DYNAMIC_DRAW, Array::USAGE_STATIC_COPY, Array::USAGE_STREAM_COPY, Array::USAGE_DYNAMIC_COPY, Array::USAGE_STATIC_READ, Array::USAGE_STREAM_READ, Array::USAGE_DYNAMIC_READ };
137	for (int usageNdx = 0; usageNdx < DE_LENGTH_OF_ARRAY(usages); usageNdx++)
138	{
139		addChild(new SingleVertexArrayUsageGroup(m_context, usages[usageNdx]));
140	}
141}
142
143class SingleVertexArrayStrideGroup : public TestCaseGroup
144{
145public:
146									SingleVertexArrayStrideGroup	(Context& context, Array::InputType type);
147	virtual							~SingleVertexArrayStrideGroup	(void);
148
149	virtual void					init							(void);
150
151private:
152									SingleVertexArrayStrideGroup	(const SingleVertexArrayStrideGroup& other);
153	SingleVertexArrayStrideGroup&	operator=						(const SingleVertexArrayStrideGroup& other);
154
155	Array::InputType				m_type;
156};
157
158SingleVertexArrayStrideGroup::SingleVertexArrayStrideGroup (Context& context, Array::InputType type)
159	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
160	, m_type		(type)
161{
162}
163
164SingleVertexArrayStrideGroup::~SingleVertexArrayStrideGroup (void)
165{
166}
167
168void SingleVertexArrayStrideGroup::init (void)
169{
170	Array::Storage		storages[]		= {Array::STORAGE_USER, Array::STORAGE_BUFFER};
171	int					counts[]		= {1, 256};
172	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
173
174	for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
175	{
176		for (int componentCount = 2; componentCount < 5; componentCount++)
177		{
178			for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
179			{
180				for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
181				{
182					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
183					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (16) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
184					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
185					const bool	bufferUnaligned	= (storages[storageNdx] == Array::STORAGE_BUFFER) && (stride % alignment) != 0;
186
187					std::string name = Array::storageToString(storages[storageNdx]) + "_stride" + typeToString(stride) + "_components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);
188
189					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
190						continue;
191
192					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
193																	Array::OUTPUTTYPE_VEC4,
194																	storages[storageNdx],
195																	Array::USAGE_DYNAMIC_DRAW,
196																	componentCount,
197																	0,
198																	stride,
199																	false,
200																	GLValue::getMinValue(m_type),
201																	GLValue::getMaxValue(m_type));
202
203					MultiVertexArrayTest::Spec spec;
204					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
205					spec.drawCount	= counts[countNdx];
206					spec.first		= 0;
207					spec.arrays.push_back(arraySpec);
208
209					if (!bufferUnaligned)
210						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
211				}
212			}
213		}
214	}
215}
216
217class SingleVertexArrayStrideTests : public TestCaseGroup
218{
219public:
220									SingleVertexArrayStrideTests	(Context& context);
221	virtual							~SingleVertexArrayStrideTests	(void);
222
223	virtual void					init							(void);
224
225private:
226									SingleVertexArrayStrideTests	(const SingleVertexArrayStrideTests& other);
227	SingleVertexArrayStrideTests&	operator=						(const SingleVertexArrayStrideTests& other);
228};
229
230SingleVertexArrayStrideTests::SingleVertexArrayStrideTests (Context& context)
231	: TestCaseGroup(context, "strides", "Single stride vertex atribute")
232{
233}
234
235SingleVertexArrayStrideTests::~SingleVertexArrayStrideTests (void)
236{
237}
238
239void SingleVertexArrayStrideTests::init (void)
240{
241	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, /*Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE,*/ Array::INPUTTYPE_FIXED, Array::INPUTTYPE_INT_2_10_10_10 };
242
243	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
244	{
245		addChild(new SingleVertexArrayStrideGroup(m_context, inputTypes[inputTypeNdx]));
246	}
247}
248
249class SingleVertexArrayFirstGroup : public TestCaseGroup
250{
251public:
252									SingleVertexArrayFirstGroup	(Context& context, Array::InputType type);
253	virtual							~SingleVertexArrayFirstGroup	(void);
254
255	virtual void					init							(void);
256
257private:
258									SingleVertexArrayFirstGroup	(const SingleVertexArrayFirstGroup& other);
259	SingleVertexArrayFirstGroup&	operator=						(const SingleVertexArrayFirstGroup& other);
260	Array::InputType				m_type;
261};
262
263SingleVertexArrayFirstGroup::SingleVertexArrayFirstGroup (Context& context, Array::InputType type)
264	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
265	, m_type		(type)
266{
267}
268
269SingleVertexArrayFirstGroup::~SingleVertexArrayFirstGroup (void)
270{
271}
272
273void SingleVertexArrayFirstGroup::init (void)
274{
275	int					counts[]		= {5, 256};
276	int					firsts[]		= {6, 24};
277	int					offsets[]		= {1, 16, 17};
278	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
279
280	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
281	{
282		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
283		{
284			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
285			{
286				for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); firstNdx++)
287				{
288					const bool	packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
289					const int	componentCount	= (packed) ? (4) : (2);
290					const int	stride			= (strides[strideNdx] < 0) ? ((packed) ? (8) : (Array::inputTypeSize(m_type) * componentCount)) : (strides[strideNdx]);
291					const int	alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
292					const bool	aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
293					std::string name			= "first" + typeToString(firsts[firstNdx]) + "_offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
294
295					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
296																	Array::OUTPUTTYPE_VEC2,
297																	Array::STORAGE_BUFFER,
298																	Array::USAGE_DYNAMIC_DRAW,
299																	componentCount,
300																	offsets[offsetNdx],
301																	stride,
302																	false,
303																	GLValue::getMinValue(m_type),
304																	GLValue::getMaxValue(m_type));
305
306					MultiVertexArrayTest::Spec spec;
307					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
308					spec.drawCount	= counts[countNdx];
309					spec.first		= firsts[firstNdx];
310					spec.arrays.push_back(arraySpec);
311
312					if (aligned)
313						addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
314				}
315			}
316		}
317	}
318}
319
320class SingleVertexArrayFirstTests : public TestCaseGroup
321{
322public:
323									SingleVertexArrayFirstTests	(Context& context);
324	virtual							~SingleVertexArrayFirstTests	(void);
325
326	virtual void					init							(void);
327
328private:
329									SingleVertexArrayFirstTests	(const SingleVertexArrayFirstTests& other);
330	SingleVertexArrayFirstTests&	operator=						(const SingleVertexArrayFirstTests& other);
331};
332
333SingleVertexArrayFirstTests::SingleVertexArrayFirstTests (Context& context)
334	: TestCaseGroup(context, "first", "Single vertex attribute, different first values to drawArrays")
335{
336}
337
338SingleVertexArrayFirstTests::~SingleVertexArrayFirstTests (void)
339{
340}
341
342void SingleVertexArrayFirstTests::init (void)
343{
344	// Test offset with different input types, component counts and storage, Usage(?)
345	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10 };
346
347	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
348	{
349		addChild(new SingleVertexArrayFirstGroup(m_context, inputTypes[inputTypeNdx]));
350	}
351}
352
353class SingleVertexArrayOffsetGroup : public TestCaseGroup
354{
355public:
356									SingleVertexArrayOffsetGroup	(Context& context, Array::InputType type);
357	virtual							~SingleVertexArrayOffsetGroup	(void);
358
359	virtual void					init							(void);
360
361private:
362									SingleVertexArrayOffsetGroup	(const SingleVertexArrayOffsetGroup& other);
363	SingleVertexArrayOffsetGroup&	operator=						(const SingleVertexArrayOffsetGroup& other);
364	Array::InputType				m_type;
365};
366
367SingleVertexArrayOffsetGroup::SingleVertexArrayOffsetGroup (Context& context, Array::InputType type)
368	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
369	, m_type		(type)
370{
371}
372
373SingleVertexArrayOffsetGroup::~SingleVertexArrayOffsetGroup (void)
374{
375}
376
377void SingleVertexArrayOffsetGroup::init (void)
378{
379	int					counts[]		= {1, 256};
380	int					offsets[]		= {1, 4, 17, 32};
381	int					strides[]		= {/*0,*/ -1, 17, 32}; // Tread negative value as sizeof input. Same as 0, but done outside of GL.
382
383	for (int offsetNdx = 0; offsetNdx < DE_LENGTH_OF_ARRAY(offsets); offsetNdx++)
384	{
385		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
386		{
387			for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
388			{
389				const bool			packed			= m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10;
390				const int			componentCount	= (packed) ? (4) : (2);
391				const int			stride			= (strides[strideNdx] < 0 ? Array::inputTypeSize(m_type) * componentCount : strides[strideNdx]);
392				const int			alignment		= (packed) ? (Array::inputTypeSize(m_type) * componentCount) : (Array::inputTypeSize(m_type));
393				const bool			aligned			= ((stride % alignment) == 0) && ((offsets[offsetNdx] % alignment) == 0);
394				const std::string	name			= "offset" + typeToString(offsets[offsetNdx]) + "_stride" + typeToString(stride) + "_quads" + typeToString(counts[countNdx]);
395
396				MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
397																Array::OUTPUTTYPE_VEC2,
398																Array::STORAGE_BUFFER,
399																Array::USAGE_DYNAMIC_DRAW,
400																componentCount,
401																offsets[offsetNdx],
402																stride,
403																false,
404																GLValue::getMinValue(m_type),
405																GLValue::getMaxValue(m_type));
406
407				MultiVertexArrayTest::Spec spec;
408				spec.primitive	= Array::PRIMITIVE_TRIANGLES;
409				spec.drawCount	= counts[countNdx];
410				spec.first		= 0;
411				spec.arrays.push_back(arraySpec);
412
413				if (aligned)
414					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
415			}
416		}
417	}
418}
419
420class SingleVertexArrayOffsetTests : public TestCaseGroup
421{
422public:
423									SingleVertexArrayOffsetTests	(Context& context);
424	virtual							~SingleVertexArrayOffsetTests	(void);
425
426	virtual void					init							(void);
427
428private:
429									SingleVertexArrayOffsetTests	(const SingleVertexArrayOffsetTests& other);
430	SingleVertexArrayOffsetTests&	operator=						(const SingleVertexArrayOffsetTests& other);
431};
432
433SingleVertexArrayOffsetTests::SingleVertexArrayOffsetTests (Context& context)
434	: TestCaseGroup(context, "offset", "Single vertex atribute offset element")
435{
436}
437
438SingleVertexArrayOffsetTests::~SingleVertexArrayOffsetTests (void)
439{
440}
441
442void SingleVertexArrayOffsetTests::init (void)
443{
444	// Test offset with different input types, component counts and storage, Usage(?)
445	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_INT_2_10_10_10 };
446
447	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
448	{
449		addChild(new SingleVertexArrayOffsetGroup(m_context, inputTypes[inputTypeNdx]));
450	}
451}
452
453class SingleVertexArrayNormalizeGroup : public TestCaseGroup
454{
455public:
456										SingleVertexArrayNormalizeGroup		(Context& context, Array::InputType type);
457	virtual								~SingleVertexArrayNormalizeGroup	(void);
458
459	virtual void						init								(void);
460
461private:
462										SingleVertexArrayNormalizeGroup		(const SingleVertexArrayNormalizeGroup& other);
463	SingleVertexArrayNormalizeGroup&	operator=							(const SingleVertexArrayNormalizeGroup& other);
464	Array::InputType					m_type;
465};
466
467SingleVertexArrayNormalizeGroup::SingleVertexArrayNormalizeGroup (Context& context, Array::InputType type)
468	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
469	, m_type		(type)
470{
471}
472
473SingleVertexArrayNormalizeGroup::~SingleVertexArrayNormalizeGroup (void)
474{
475}
476
477void SingleVertexArrayNormalizeGroup::init (void)
478{
479	int					counts[]		= {1, 256};
480
481	for (int componentCount = 2; componentCount < 5; componentCount++)
482	{
483		for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
484		{
485			if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
486				continue;
487
488			std::string name = "components" + typeToString(componentCount) + "_quads" + typeToString(counts[countNdx]);
489
490			MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
491															Array::OUTPUTTYPE_VEC4,
492															Array::STORAGE_USER,
493															Array::USAGE_DYNAMIC_DRAW,
494															componentCount,
495															0,
496															0,
497															true,
498															GLValue::getMinValue(m_type),
499															GLValue::getMaxValue(m_type));
500
501			MultiVertexArrayTest::Spec spec;
502			spec.primitive	= Array::PRIMITIVE_TRIANGLES;
503			spec.drawCount	= counts[countNdx];
504			spec.first		= 0;
505			spec.arrays.push_back(arraySpec);
506
507			addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
508		}
509	}
510}
511
512class SingleVertexArrayNormalizeTests : public TestCaseGroup
513{
514public:
515										SingleVertexArrayNormalizeTests		(Context& context);
516	virtual								~SingleVertexArrayNormalizeTests	(void);
517
518	virtual void						init								(void);
519
520private:
521										SingleVertexArrayNormalizeTests		(const SingleVertexArrayNormalizeTests& other);
522	SingleVertexArrayNormalizeTests&	operator=							(const SingleVertexArrayNormalizeTests& other);
523};
524
525SingleVertexArrayNormalizeTests::SingleVertexArrayNormalizeTests (Context& context)
526	: TestCaseGroup(context, "normalize", "Single normalize vertex atribute")
527{
528}
529
530SingleVertexArrayNormalizeTests::~SingleVertexArrayNormalizeTests (void)
531{
532}
533
534void SingleVertexArrayNormalizeTests::init (void)
535{
536	// Test normalization with different input types, component counts and storage
537	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT, Array::INPUTTYPE_HALF , Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10, Array::INPUTTYPE_INT_2_10_10_10 };
538
539	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
540	{
541		addChild(new SingleVertexArrayNormalizeGroup(m_context, inputTypes[inputTypeNdx]));
542	}
543}
544
545class SingleVertexArrayOutputTypeGroup : public TestCaseGroup
546{
547public:
548										SingleVertexArrayOutputTypeGroup	(Context& context, Array::InputType type);
549	virtual								~SingleVertexArrayOutputTypeGroup	(void);
550
551	virtual void						init								(void);
552
553private:
554										SingleVertexArrayOutputTypeGroup	(const SingleVertexArrayOutputTypeGroup& other);
555	SingleVertexArrayOutputTypeGroup&	operator=							(const SingleVertexArrayOutputTypeGroup& other);
556	Array::InputType					m_type;
557};
558
559SingleVertexArrayOutputTypeGroup::SingleVertexArrayOutputTypeGroup (Context& context, Array::InputType type)
560	: TestCaseGroup	(context, Array::inputTypeToString(type).c_str(), Array::inputTypeToString(type).c_str())
561	, m_type		(type)
562{
563}
564
565SingleVertexArrayOutputTypeGroup::~SingleVertexArrayOutputTypeGroup (void)
566{
567}
568
569void SingleVertexArrayOutputTypeGroup::init (void)
570{
571	Array::OutputType	outputTypes[]	= {Array::OUTPUTTYPE_VEC2, Array::OUTPUTTYPE_VEC3, Array::OUTPUTTYPE_VEC4, Array::OUTPUTTYPE_IVEC2, Array::OUTPUTTYPE_IVEC3, Array::OUTPUTTYPE_IVEC4, Array::OUTPUTTYPE_UVEC2, Array::OUTPUTTYPE_UVEC3, Array::OUTPUTTYPE_UVEC4 };
572	Array::Storage		storages[]		= {Array::STORAGE_USER};
573	int					counts[]		= {1, 256};
574
575	for (int outputTypeNdx = 0; outputTypeNdx < DE_LENGTH_OF_ARRAY(outputTypes); outputTypeNdx++)
576	{
577		for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
578		{
579			for (int componentCount = 2; componentCount < 5; componentCount++)
580			{
581				for (int countNdx = 0; countNdx < DE_LENGTH_OF_ARRAY(counts); countNdx++)
582				{
583					std::string name = "components" + typeToString(componentCount) + "_" + Array::outputTypeToString(outputTypes[outputTypeNdx]) + "_quads" + typeToString(counts[countNdx]);
584
585					const bool inputIsSignedInteger		= m_type == Array::INPUTTYPE_INT || m_type == Array::INPUTTYPE_SHORT || m_type == Array::INPUTTYPE_BYTE;
586					const bool inputIsUnignedInteger	= m_type == Array::INPUTTYPE_UNSIGNED_INT || m_type == Array::INPUTTYPE_UNSIGNED_SHORT || m_type == Array::INPUTTYPE_UNSIGNED_BYTE;
587					const bool outputIsSignedInteger	= outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC2 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC3 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_IVEC4;
588					const bool outputIsUnsignedInteger	= outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC2 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC3 || outputTypes[outputTypeNdx] == Array::OUTPUTTYPE_UVEC4;
589
590					// If input type is float type and output type is int type skip
591					if ((m_type == Array::INPUTTYPE_FLOAT ||  m_type == Array::INPUTTYPE_HALF || m_type == Array::INPUTTYPE_FIXED) && (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
592						continue;
593
594					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && (outputTypes[outputTypeNdx] >= Array::OUTPUTTYPE_INT))
595						continue;
596
597					if((m_type == Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10 || m_type == Array::INPUTTYPE_INT_2_10_10_10) && componentCount != 4)
598						continue;
599
600					// Loading signed data as unsigned causes undefined values and vice versa
601					if (inputIsSignedInteger && outputIsUnsignedInteger)
602						continue;
603					if (inputIsUnignedInteger && outputIsSignedInteger)
604						continue;
605
606					MultiVertexArrayTest::Spec::ArraySpec arraySpec(m_type,
607																	outputTypes[outputTypeNdx],
608																	storages[storageNdx],
609																	Array::USAGE_DYNAMIC_DRAW,
610																	componentCount,
611																	0,
612																	0,
613																	false,
614																	GLValue::getMinValue(m_type),
615																	GLValue::getMaxValue(m_type));
616
617					MultiVertexArrayTest::Spec spec;
618					spec.primitive	= Array::PRIMITIVE_TRIANGLES;
619					spec.drawCount	= counts[countNdx];
620					spec.first		= 0;
621					spec.arrays.push_back(arraySpec);
622
623					addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), name.c_str()));
624				}
625			}
626		}
627	}
628}
629
630class SingleVertexArrayOutputTypeTests : public TestCaseGroup
631{
632public:
633										SingleVertexArrayOutputTypeTests	(Context& context);
634	virtual								~SingleVertexArrayOutputTypeTests	(void);
635
636	virtual void						init								(void);
637
638private:
639										SingleVertexArrayOutputTypeTests	(const SingleVertexArrayOutputTypeTests& other);
640	SingleVertexArrayOutputTypeTests&	operator=							(const SingleVertexArrayOutputTypeTests& other);
641};
642
643SingleVertexArrayOutputTypeTests::SingleVertexArrayOutputTypeTests (Context& context)
644	: TestCaseGroup(context, "output_types", "Single output type vertex atribute")
645{
646}
647
648SingleVertexArrayOutputTypeTests::~SingleVertexArrayOutputTypeTests (void)
649{
650}
651
652void SingleVertexArrayOutputTypeTests::init (void)
653{
654	// Test output types with different input types, component counts and storage, Usage?, Precision?, float?
655	Array::InputType	inputTypes[]	= {Array::INPUTTYPE_FLOAT, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_FIXED, Array::INPUTTYPE_UNSIGNED_INT, Array::INPUTTYPE_INT, Array::INPUTTYPE_HALF, Array::INPUTTYPE_UNSIGNED_INT_2_10_10_10, Array::INPUTTYPE_INT_2_10_10_10 };
656
657	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
658	{
659		addChild(new SingleVertexArrayOutputTypeGroup(m_context, inputTypes[inputTypeNdx]));
660	}
661}
662
663
664class SingleVertexArrayTestGroup : public TestCaseGroup
665{
666public:
667									SingleVertexArrayTestGroup	(Context& context);
668	virtual							~SingleVertexArrayTestGroup	(void);
669
670	virtual void					init						(void);
671
672private:
673									SingleVertexArrayTestGroup	(const SingleVertexArrayTestGroup& other);
674	SingleVertexArrayTestGroup&		operator=					(const SingleVertexArrayTestGroup& other);
675};
676
677SingleVertexArrayTestGroup::SingleVertexArrayTestGroup (Context& context)
678	: TestCaseGroup(context, "single_attribute", "Single vertex atribute")
679{
680}
681
682SingleVertexArrayTestGroup::~SingleVertexArrayTestGroup (void)
683{
684}
685
686void SingleVertexArrayTestGroup::init (void)
687{
688	addChild(new SingleVertexArrayStrideTests(m_context));
689	addChild(new SingleVertexArrayNormalizeTests(m_context));
690	addChild(new SingleVertexArrayOutputTypeTests(m_context));
691	addChild(new SingleVertexArrayUsageTests(m_context));
692	addChild(new SingleVertexArrayOffsetTests(m_context));
693	addChild(new SingleVertexArrayFirstTests(m_context));
694}
695
696class MultiVertexArrayCountTests : public TestCaseGroup
697{
698public:
699									MultiVertexArrayCountTests	(Context& context);
700	virtual							~MultiVertexArrayCountTests	(void);
701
702	virtual void					init						(void);
703
704private:
705									MultiVertexArrayCountTests	(const MultiVertexArrayCountTests& other);
706	MultiVertexArrayCountTests&		operator=					(const MultiVertexArrayCountTests& other);
707
708	std::string						getTestName					(const MultiVertexArrayTest::Spec& spec);
709};
710
711MultiVertexArrayCountTests::MultiVertexArrayCountTests (Context& context)
712	: TestCaseGroup(context, "attribute_count", "Attribute counts")
713{
714}
715
716MultiVertexArrayCountTests::~MultiVertexArrayCountTests (void)
717{
718}
719
720std::string MultiVertexArrayCountTests::getTestName (const MultiVertexArrayTest::Spec& spec)
721{
722	std::stringstream name;
723	name
724		<< spec.arrays.size();
725
726	return name.str();
727}
728
729void MultiVertexArrayCountTests::init (void)
730{
731	// Test attribute counts
732	int arrayCounts[] = {2, 3, 4, 5, 6, 7, 8};
733
734	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
735	{
736		MultiVertexArrayTest::Spec spec;
737
738		spec.primitive	= Array::PRIMITIVE_TRIANGLES;
739		spec.drawCount	= 256;
740		spec.first		= 0;
741
742		for (int arrayNdx = 0; arrayNdx < arrayCounts[arrayCountNdx]; arrayNdx++)
743		{
744			MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
745															Array::OUTPUTTYPE_VEC2,
746															Array::STORAGE_USER,
747															Array::USAGE_DYNAMIC_DRAW,
748															2,
749															0,
750															0,
751															false,
752															GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
753															GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
754
755			spec.arrays.push_back(arraySpec);
756		}
757
758		std::string name = getTestName(spec);
759		std::string desc = getTestName(spec);
760
761		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
762	}
763}
764
765class MultiVertexArrayStorageTests : public TestCaseGroup
766{
767public:
768									MultiVertexArrayStorageTests	(Context& context);
769	virtual							~MultiVertexArrayStorageTests	(void);
770
771	virtual void					init							(void);
772
773private:
774									MultiVertexArrayStorageTests	(const MultiVertexArrayStorageTests& other);
775	MultiVertexArrayStorageTests&	operator=						(const MultiVertexArrayStorageTests& other);
776
777	void							addStorageCases 				(MultiVertexArrayTest::Spec spec, int depth);
778	std::string						getTestName						(const MultiVertexArrayTest::Spec& spec);
779};
780
781MultiVertexArrayStorageTests::MultiVertexArrayStorageTests (Context& context)
782	: TestCaseGroup(context, "storage", "Attribute storages")
783{
784}
785
786MultiVertexArrayStorageTests::~MultiVertexArrayStorageTests (void)
787{
788}
789
790std::string MultiVertexArrayStorageTests::getTestName (const MultiVertexArrayTest::Spec& spec)
791{
792	std::stringstream name;
793	name
794		<< spec.arrays.size();
795
796	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
797	{
798		name
799			<< "_"
800			<< Array::storageToString(spec.arrays[arrayNdx].storage);
801	}
802
803	return name.str();
804}
805
806void MultiVertexArrayStorageTests::addStorageCases (MultiVertexArrayTest::Spec spec, int depth)
807{
808	if (depth == 0)
809	{
810		// Skip trivial case, used elsewhere
811		bool ok = false;
812		for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
813		{
814			if (spec.arrays[arrayNdx].storage != Array::STORAGE_USER)
815			{
816				ok = true;
817				break;
818			}
819		}
820
821		if (!ok)
822			return;
823
824		std::string name = getTestName(spec);
825		std::string desc = getTestName(spec);
826
827		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
828		return;
829	}
830
831	Array::Storage storages[] = {Array::STORAGE_USER, Array::STORAGE_BUFFER};
832	for (int storageNdx = 0; storageNdx < DE_LENGTH_OF_ARRAY(storages); storageNdx++)
833	{
834		MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
835														Array::OUTPUTTYPE_VEC2,
836														storages[storageNdx],
837														Array::USAGE_DYNAMIC_DRAW,
838														2,
839														0,
840														0,
841														false,
842														GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
843														GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
844
845		MultiVertexArrayTest::Spec _spec = spec;
846		_spec.arrays.push_back(arraySpec);
847		addStorageCases(_spec, depth-1);
848	}
849}
850
851
852void MultiVertexArrayStorageTests::init (void)
853{
854	// Test different storages
855	int arrayCounts[] = {3};
856
857	MultiVertexArrayTest::Spec spec;
858
859	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
860	spec.drawCount	= 256;
861	spec.first		= 0;
862
863	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
864		addStorageCases(spec, arrayCounts[arrayCountNdx]);
865}
866
867class MultiVertexArrayStrideTests : public TestCaseGroup
868{
869public:
870									MultiVertexArrayStrideTests		(Context& context);
871	virtual							~MultiVertexArrayStrideTests	(void);
872
873	virtual void					init							(void);
874
875private:
876									MultiVertexArrayStrideTests		(const MultiVertexArrayStrideTests& other);
877	MultiVertexArrayStrideTests&	operator=						(const MultiVertexArrayStrideTests& other);
878
879	void							addStrideCases 					(MultiVertexArrayTest::Spec spec, int depth);
880	std::string						getTestName						(const MultiVertexArrayTest::Spec& spec);
881};
882
883MultiVertexArrayStrideTests::MultiVertexArrayStrideTests (Context& context)
884	: TestCaseGroup(context, "stride", "Strides")
885{
886}
887
888MultiVertexArrayStrideTests::~MultiVertexArrayStrideTests (void)
889{
890}
891
892std::string MultiVertexArrayStrideTests::getTestName (const MultiVertexArrayTest::Spec& spec)
893{
894	std::stringstream name;
895
896	name
897		<< spec.arrays.size();
898
899	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
900	{
901		name
902			<< "_"
903			<< Array::inputTypeToString(spec.arrays[arrayNdx].inputType)
904			<< spec.arrays[arrayNdx].componentCount << "_"
905			<< spec.arrays[arrayNdx].stride;
906	}
907
908	return name.str();
909}
910
911void MultiVertexArrayStrideTests::init (void)
912{
913	// Test different strides, with multiple arrays, input types??
914	int arrayCounts[] = {3};
915
916	MultiVertexArrayTest::Spec spec;
917
918	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
919	spec.drawCount	= 256;
920	spec.first		= 0;
921
922	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
923		addStrideCases(spec, arrayCounts[arrayCountNdx]);
924}
925
926void MultiVertexArrayStrideTests::addStrideCases (MultiVertexArrayTest::Spec spec, int depth)
927{
928	if (depth == 0)
929	{
930		std::string name = getTestName(spec);
931		std::string desc = getTestName(spec);
932		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
933		return;
934	}
935
936	int strides[]	= {0, -1, 17, 32};
937
938	for (int strideNdx = 0; strideNdx < DE_LENGTH_OF_ARRAY(strides); strideNdx++)
939	{
940		const int componentCount = 2;
941		MultiVertexArrayTest::Spec::ArraySpec arraySpec(Array::INPUTTYPE_FLOAT,
942														Array::OUTPUTTYPE_VEC2,
943														Array::STORAGE_USER,
944														Array::USAGE_DYNAMIC_DRAW,
945														componentCount,
946														0,
947														(strides[strideNdx] >= 0 ? strides[strideNdx] : componentCount * Array::inputTypeSize(Array::INPUTTYPE_FLOAT)),
948														false,
949														GLValue::getMinValue(Array::INPUTTYPE_FLOAT),
950														GLValue::getMaxValue(Array::INPUTTYPE_FLOAT));
951
952		MultiVertexArrayTest::Spec _spec = spec;
953		_spec.arrays.push_back(arraySpec);
954		addStrideCases(_spec, depth-1);
955	}
956}
957
958class MultiVertexArrayOutputTests : public TestCaseGroup
959{
960public:
961										MultiVertexArrayOutputTests		(Context& context);
962	virtual								~MultiVertexArrayOutputTests	(void);
963
964	virtual void						init								(void);
965
966private:
967										MultiVertexArrayOutputTests		(const MultiVertexArrayOutputTests& other);
968	MultiVertexArrayOutputTests&	operator=							(const MultiVertexArrayOutputTests& other);
969
970	void								addInputTypeCases 					(MultiVertexArrayTest::Spec spec, int depth);
971	std::string							getTestName							(const MultiVertexArrayTest::Spec& spec);
972};
973
974MultiVertexArrayOutputTests::MultiVertexArrayOutputTests (Context& context)
975	: TestCaseGroup(context, "input_types", "input types")
976{
977}
978
979MultiVertexArrayOutputTests::~MultiVertexArrayOutputTests (void)
980{
981}
982
983std::string MultiVertexArrayOutputTests::getTestName (const MultiVertexArrayTest::Spec& spec)
984{
985	std::stringstream name;
986
987	name
988		<< spec.arrays.size();
989
990	for (int arrayNdx = 0; arrayNdx < (int)spec.arrays.size(); arrayNdx++)
991	{
992		name
993			<< "_"
994			<< Array::inputTypeToString(spec.arrays[arrayNdx].inputType)
995			<< spec.arrays[arrayNdx].componentCount << "_"
996			<< Array::outputTypeToString(spec.arrays[arrayNdx].outputType);
997	}
998
999	return name.str();
1000}
1001
1002void MultiVertexArrayOutputTests::init (void)
1003{
1004	// Test different input types, with multiple arrays
1005	int arrayCounts[] = {3};
1006
1007	MultiVertexArrayTest::Spec spec;
1008
1009	spec.primitive	= Array::PRIMITIVE_TRIANGLES;
1010	spec.drawCount	= 256;
1011	spec.first		= 0;
1012
1013	for (int arrayCountNdx = 0; arrayCountNdx < DE_LENGTH_OF_ARRAY(arrayCounts); arrayCountNdx++)
1014		addInputTypeCases(spec, arrayCounts[arrayCountNdx]);
1015}
1016
1017void MultiVertexArrayOutputTests::addInputTypeCases (MultiVertexArrayTest::Spec spec, int depth)
1018{
1019	if (depth == 0)
1020	{
1021		std::string name = getTestName(spec);
1022		std::string desc = getTestName(spec);
1023		addChild(new MultiVertexArrayTest(m_testCtx, m_context.getRenderContext(), spec, name.c_str(), desc.c_str()));
1024		return;
1025	}
1026
1027	Array::InputType inputTypes[] = {Array::INPUTTYPE_FIXED, Array::INPUTTYPE_BYTE, Array::INPUTTYPE_SHORT, Array::INPUTTYPE_UNSIGNED_BYTE, Array::INPUTTYPE_UNSIGNED_SHORT};
1028	for (int inputTypeNdx = 0; inputTypeNdx < DE_LENGTH_OF_ARRAY(inputTypes); inputTypeNdx++)
1029	{
1030		MultiVertexArrayTest::Spec::ArraySpec arraySpec(inputTypes[inputTypeNdx],
1031														Array::OUTPUTTYPE_VEC2,
1032														Array::STORAGE_USER,
1033														Array::USAGE_DYNAMIC_DRAW,
1034														2,
1035														0,
1036														0,
1037														false,
1038														GLValue::getMinValue(inputTypes[inputTypeNdx]),
1039														GLValue::getMaxValue(inputTypes[inputTypeNdx]));
1040
1041		MultiVertexArrayTest::Spec _spec = spec;
1042		_spec.arrays.push_back(arraySpec);
1043		addInputTypeCases(_spec, depth-1);
1044	}
1045}
1046
1047class MultiVertexArrayTestGroup : public TestCaseGroup
1048{
1049public:
1050									MultiVertexArrayTestGroup	(Context& context);
1051	virtual							~MultiVertexArrayTestGroup	(void);
1052
1053	virtual void					init						(void);
1054
1055private:
1056									MultiVertexArrayTestGroup	(const MultiVertexArrayTestGroup& other);
1057	MultiVertexArrayTestGroup&		operator=					(const MultiVertexArrayTestGroup& other);
1058};
1059
1060MultiVertexArrayTestGroup::MultiVertexArrayTestGroup (Context& context)
1061	: TestCaseGroup(context, "multiple_attributes", "Multiple vertex atributes")
1062{
1063}
1064
1065MultiVertexArrayTestGroup::~MultiVertexArrayTestGroup (void)
1066{
1067}
1068
1069void MultiVertexArrayTestGroup::init (void)
1070{
1071	addChild(new MultiVertexArrayCountTests(m_context));
1072	addChild(new MultiVertexArrayStorageTests(m_context));
1073	addChild(new MultiVertexArrayStrideTests(m_context));
1074	addChild(new MultiVertexArrayOutputTests(m_context));
1075}
1076
1077VertexArrayTestGroup::VertexArrayTestGroup (Context& context)
1078	: TestCaseGroup(context, "vertex_arrays", "Vertex array and array tests")
1079{
1080}
1081
1082VertexArrayTestGroup::~VertexArrayTestGroup (void)
1083{
1084}
1085
1086void VertexArrayTestGroup::init (void)
1087{
1088	addChild(new SingleVertexArrayTestGroup(m_context));
1089	addChild(new MultiVertexArrayTestGroup(m_context));
1090}
1091
1092} // Functional
1093} // gles3
1094} // deqp
1095