Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 2.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 Drawing tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es2fDrawTests.hpp"
     25 #include "glsDrawTest.hpp"
     26 #include "tcuRenderTarget.hpp"
     27 #include "deRandom.hpp"
     28 #include "deStringUtil.hpp"
     29 #include "deUniquePtr.hpp"
     30 #include "deSTLUtil.hpp"
     31 
     32 #include "glwEnums.hpp"
     33 
     34 #include <set>
     35 
     36 namespace deqp
     37 {
     38 namespace gles2
     39 {
     40 namespace Functional
     41 {
     42 namespace
     43 {
     44 
     45 enum TestIterationType
     46 {
     47 	TYPE_DRAW_COUNT,		// !< test with 1, 5, and 25 primitives
     48 
     49 	TYPE_LAST
     50 };
     51 
     52 static void addTestIterations (gls::DrawTest* test, const gls::DrawTestSpec& baseSpec, TestIterationType type)
     53 {
     54 	gls::DrawTestSpec spec(baseSpec);
     55 
     56 	if (type == TYPE_DRAW_COUNT)
     57 	{
     58 		spec.primitiveCount = 1;
     59 		test->addIteration(spec, "draw count = 1");
     60 
     61 		spec.primitiveCount = 5;
     62 		test->addIteration(spec, "draw count = 5");
     63 
     64 		spec.primitiveCount = 25;
     65 		test->addIteration(spec, "draw count = 25");
     66 	}
     67 	else
     68 		DE_ASSERT(false);
     69 }
     70 
     71 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
     72 {
     73 	spec.apiType							= glu::ApiType::es(2,0);
     74 	spec.primitive							= gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
     75 	spec.primitiveCount						= 5;
     76 	spec.drawMethod							= method;
     77 	spec.indexType							= gls::DrawTestSpec::INDEXTYPE_LAST;
     78 	spec.indexPointerOffset					= 0;
     79 	spec.indexStorage						= gls::DrawTestSpec::STORAGE_LAST;
     80 	spec.first								= 0;
     81 	spec.indexMin							= 0;
     82 	spec.indexMax							= 0;
     83 	spec.instanceCount						= 1;
     84 
     85 	spec.attribs.resize(2);
     86 
     87 	spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
     88 	spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
     89 	spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
     90 	spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
     91 	spec.attribs[0].componentCount			= 4;
     92 	spec.attribs[0].offset					= 0;
     93 	spec.attribs[0].stride					= 0;
     94 	spec.attribs[0].normalize				= false;
     95 	spec.attribs[0].instanceDivisor			= 0;
     96 	spec.attribs[0].useDefaultAttribute		= false;
     97 
     98 	spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
     99 	spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    100 	spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    101 	spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    102 	spec.attribs[1].componentCount			= 2;
    103 	spec.attribs[1].offset					= 0;
    104 	spec.attribs[1].stride					= 0;
    105 	spec.attribs[1].normalize				= false;
    106 	spec.attribs[1].instanceDivisor			= 0;
    107 	spec.attribs[1].useDefaultAttribute		= false;
    108 }
    109 
    110 
    111 class AttributeGroup : public TestCaseGroup
    112 {
    113 public:
    114 									AttributeGroup	(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage);
    115 									~AttributeGroup	(void);
    116 
    117 	void							init			(void);
    118 
    119 private:
    120 	gls::DrawTestSpec::DrawMethod	m_method;
    121 	gls::DrawTestSpec::Primitive	m_primitive;
    122 	gls::DrawTestSpec::IndexType	m_indexType;
    123 	gls::DrawTestSpec::Storage		m_indexStorage;
    124 };
    125 
    126 AttributeGroup::AttributeGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod, gls::DrawTestSpec::Primitive primitive, gls::DrawTestSpec::IndexType indexType, gls::DrawTestSpec::Storage indexStorage)
    127 	: TestCaseGroup		(context, name, descr)
    128 	, m_method			(drawMethod)
    129 	, m_primitive		(primitive)
    130 	, m_indexType		(indexType)
    131 	, m_indexStorage	(indexStorage)
    132 {
    133 }
    134 
    135 AttributeGroup::~AttributeGroup (void)
    136 {
    137 }
    138 
    139 void AttributeGroup::init (void)
    140 {
    141 	// Single attribute
    142 	{
    143 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
    144 		gls::DrawTestSpec	spec;
    145 
    146 		spec.apiType							= glu::ApiType::es(2,0);
    147 		spec.primitive							= m_primitive;
    148 		spec.primitiveCount						= 0;
    149 		spec.drawMethod							= m_method;
    150 		spec.indexType							= m_indexType;
    151 		spec.indexPointerOffset					= 0;
    152 		spec.indexStorage						= m_indexStorage;
    153 		spec.first								= 0;
    154 		spec.indexMin							= 0;
    155 		spec.indexMax							= 0;
    156 		spec.instanceCount						= 1;
    157 
    158 		spec.attribs.resize(1);
    159 
    160 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    161 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    162 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    163 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    164 		spec.attribs[0].componentCount			= 2;
    165 		spec.attribs[0].offset					= 0;
    166 		spec.attribs[0].stride					= 0;
    167 		spec.attribs[0].normalize				= false;
    168 		spec.attribs[0].instanceDivisor			= 0;
    169 		spec.attribs[0].useDefaultAttribute		= false;
    170 
    171 		addTestIterations(test, spec, TYPE_DRAW_COUNT);
    172 
    173 		this->addChild(test);
    174 	}
    175 
    176 	// Multiple attribute
    177 	{
    178 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays");
    179 		gls::DrawTestSpec	spec;
    180 
    181 		spec.apiType							= glu::ApiType::es(2,0);
    182 		spec.primitive							= m_primitive;
    183 		spec.primitiveCount						= 0;
    184 		spec.drawMethod							= m_method;
    185 		spec.indexType							= m_indexType;
    186 		spec.indexPointerOffset					= 0;
    187 		spec.indexStorage						= m_indexStorage;
    188 		spec.first								= 0;
    189 		spec.indexMin							= 0;
    190 		spec.indexMax							= 0;
    191 		spec.instanceCount						= 1;
    192 
    193 		spec.attribs.resize(2);
    194 
    195 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    196 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    197 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    198 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    199 		spec.attribs[0].componentCount			= 4;
    200 		spec.attribs[0].offset					= 0;
    201 		spec.attribs[0].stride					= 0;
    202 		spec.attribs[0].normalize				= false;
    203 		spec.attribs[0].instanceDivisor			= 0;
    204 		spec.attribs[0].useDefaultAttribute		= false;
    205 
    206 		spec.attribs[1].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    207 		spec.attribs[1].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    208 		spec.attribs[1].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    209 		spec.attribs[1].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    210 		spec.attribs[1].componentCount			= 2;
    211 		spec.attribs[1].offset					= 0;
    212 		spec.attribs[1].stride					= 0;
    213 		spec.attribs[1].normalize				= false;
    214 		spec.attribs[1].instanceDivisor			= 0;
    215 		spec.attribs[1].useDefaultAttribute		= false;
    216 
    217 		addTestIterations(test, spec, TYPE_DRAW_COUNT);
    218 
    219 		this->addChild(test);
    220 	}
    221 
    222 	// Multiple attribute, second one default.
    223 	{
    224 		gls::DrawTest*		test				= new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
    225 		gls::DrawTestSpec	spec;
    226 
    227 		spec.apiType							= glu::ApiType::es(2,0);
    228 		spec.primitive							= m_primitive;
    229 		spec.primitiveCount						= 5;
    230 		spec.drawMethod							= m_method;
    231 		spec.indexType							= m_indexType;
    232 		spec.indexPointerOffset					= 0;
    233 		spec.indexStorage						= m_indexStorage;
    234 		spec.first								= 0;
    235 		spec.indexMin							= 0;
    236 		spec.indexMax							= 0;
    237 		spec.instanceCount						= 1;
    238 
    239 		spec.attribs.resize(2);
    240 
    241 		spec.attribs[0].inputType				= gls::DrawTestSpec::INPUTTYPE_FLOAT;
    242 		spec.attribs[0].outputType				= gls::DrawTestSpec::OUTPUTTYPE_VEC2;
    243 		spec.attribs[0].storage					= gls::DrawTestSpec::STORAGE_BUFFER;
    244 		spec.attribs[0].usage					= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    245 		spec.attribs[0].componentCount			= 2;
    246 		spec.attribs[0].offset					= 0;
    247 		spec.attribs[0].stride					= 0;
    248 		spec.attribs[0].normalize				= false;
    249 		spec.attribs[0].instanceDivisor			= 0;
    250 		spec.attribs[0].useDefaultAttribute		= false;
    251 
    252 		struct IOPair
    253 		{
    254 			gls::DrawTestSpec::InputType  input;
    255 			gls::DrawTestSpec::OutputType output;
    256 			int							  componentCount;
    257 		} iopairs[] =
    258 		{
    259 			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
    260 			{ gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
    261 		};
    262 
    263 		for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
    264 		{
    265 			const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
    266 
    267 			spec.attribs[1].inputType			= iopairs[ioNdx].input;
    268 			spec.attribs[1].outputType			= iopairs[ioNdx].output;
    269 			spec.attribs[1].storage				= gls::DrawTestSpec::STORAGE_BUFFER;
    270 			spec.attribs[1].usage				= gls::DrawTestSpec::USAGE_STATIC_DRAW;
    271 			spec.attribs[1].componentCount		= iopairs[ioNdx].componentCount;
    272 			spec.attribs[1].offset				= 0;
    273 			spec.attribs[1].stride				= 0;
    274 			spec.attribs[1].normalize			= false;
    275 			spec.attribs[1].instanceDivisor		= 0;
    276 			spec.attribs[1].useDefaultAttribute	= true;
    277 
    278 			test->addIteration(spec, desc.c_str());
    279 		}
    280 
    281 		this->addChild(test);
    282 	}
    283 }
    284 
    285 class IndexGroup : public TestCaseGroup
    286 {
    287 public:
    288 									IndexGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    289 									~IndexGroup		(void);
    290 
    291 	void							init			(void);
    292 
    293 private:
    294 	gls::DrawTestSpec::DrawMethod	m_method;
    295 };
    296 
    297 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    298 	: TestCaseGroup		(context, name, descr)
    299 	, m_method			(drawMethod)
    300 {
    301 }
    302 
    303 IndexGroup::~IndexGroup (void)
    304 {
    305 }
    306 
    307 void IndexGroup::init (void)
    308 {
    309 	struct IndexTest
    310 	{
    311 		gls::DrawTestSpec::Storage		storage;
    312 		gls::DrawTestSpec::IndexType	type;
    313 		bool							aligned;
    314 		int								offsets[3];
    315 	};
    316 
    317 	const IndexTest tests[] =
    318 	{
    319 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
    320 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
    321 
    322 		{ gls::DrawTestSpec::STORAGE_USER,		gls::DrawTestSpec::INDEXTYPE_SHORT,	false,	{ 1, 3, -1 } },
    323 
    324 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_BYTE,	true,	{ 0, 1, -1 } },
    325 		{ gls::DrawTestSpec::STORAGE_BUFFER,	gls::DrawTestSpec::INDEXTYPE_SHORT,	true,	{ 0, 2, -1 } },
    326 	};
    327 
    328 	gls::DrawTestSpec spec;
    329 
    330 	tcu::TestCaseGroup* userPtrGroup			= new tcu::TestCaseGroup(m_testCtx, "user_ptr", "user pointer");
    331 	tcu::TestCaseGroup* unalignedUserPtrGroup	= new tcu::TestCaseGroup(m_testCtx, "unaligned_user_ptr", "unaligned user pointer");
    332 	tcu::TestCaseGroup* bufferGroup				= new tcu::TestCaseGroup(m_testCtx, "buffer", "buffer");
    333 
    334 	genBasicSpec(spec, m_method);
    335 
    336 	this->addChild(userPtrGroup);
    337 	this->addChild(unalignedUserPtrGroup);
    338 	this->addChild(bufferGroup);
    339 
    340 	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
    341 	{
    342 		const IndexTest&				indexTest	= tests[testNdx];
    343 		tcu::TestCaseGroup*				group		= (indexTest.storage == gls::DrawTestSpec::STORAGE_USER)
    344 													? ((indexTest.aligned) ? (userPtrGroup) : (unalignedUserPtrGroup))
    345 													: ((indexTest.aligned) ? (bufferGroup) : (DE_NULL));
    346 
    347 		const std::string				name		= std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
    348 		const std::string				desc		= std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type) + " in " + gls::DrawTestSpec::storageToString(indexTest.storage);
    349 		de::MovePtr<gls::DrawTest>		test		(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str()));
    350 
    351 		spec.indexType			= indexTest.type;
    352 		spec.indexStorage		= indexTest.storage;
    353 
    354 		for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
    355 		{
    356 			const std::string iterationDesc = std::string("offset ") + de::toString(indexTest.offsets[iterationNdx]);
    357 			spec.indexPointerOffset	= indexTest.offsets[iterationNdx];
    358 			test->addIteration(spec, iterationDesc.c_str());
    359 		}
    360 
    361 		DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET);
    362 		DE_ASSERT(spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE);
    363 		group->addChild(test.release());
    364 	}
    365 }
    366 
    367 
    368 class FirstGroup : public TestCaseGroup
    369 {
    370 public:
    371 									FirstGroup		(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    372 									~FirstGroup		(void);
    373 
    374 	void							init			(void);
    375 
    376 private:
    377 	gls::DrawTestSpec::DrawMethod	m_method;
    378 };
    379 
    380 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    381 	: TestCaseGroup		(context, name, descr)
    382 	, m_method			(drawMethod)
    383 {
    384 }
    385 
    386 FirstGroup::~FirstGroup (void)
    387 {
    388 }
    389 
    390 void FirstGroup::init (void)
    391 {
    392 	const int firsts[] =
    393 	{
    394 		0, 1, 17
    395 	};
    396 
    397 	gls::DrawTestSpec spec;
    398 	genBasicSpec(spec, m_method);
    399 
    400 	for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
    401 	{
    402 		const std::string	name = std::string("first_") + de::toString(firsts[firstNdx]);
    403 		const std::string	desc = std::string("first ") + de::toString(firsts[firstNdx]);
    404 		gls::DrawTest*		test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
    405 
    406 		spec.first = firsts[firstNdx];
    407 
    408 		addTestIterations(test, spec, TYPE_DRAW_COUNT);
    409 
    410 		this->addChild(test);
    411 	}
    412 }
    413 
    414 class MethodGroup : public TestCaseGroup
    415 {
    416 public:
    417 									MethodGroup			(Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
    418 									~MethodGroup		(void);
    419 
    420 	void							init				(void);
    421 
    422 private:
    423 	gls::DrawTestSpec::DrawMethod	m_method;
    424 };
    425 
    426 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
    427 	: TestCaseGroup		(context, name, descr)
    428 	, m_method			(drawMethod)
    429 {
    430 }
    431 
    432 MethodGroup::~MethodGroup (void)
    433 {
    434 }
    435 
    436 void MethodGroup::init (void)
    437 {
    438 	const bool indexed		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED);
    439 	const bool hasFirst		= (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS) || (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INSTANCED);
    440 
    441 	const gls::DrawTestSpec::Primitive primitive[] =
    442 	{
    443 		gls::DrawTestSpec::PRIMITIVE_POINTS,
    444 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
    445 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
    446 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
    447 		gls::DrawTestSpec::PRIMITIVE_LINES,
    448 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
    449 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
    450 	};
    451 
    452 	if (hasFirst)
    453 	{
    454 		// First-tests
    455 		this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
    456 	}
    457 
    458 	if (indexed)
    459 	{
    460 		// Index-tests
    461 		if (m_method != gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED)
    462 			this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
    463 	}
    464 
    465 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
    466 	{
    467 		const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
    468 		const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
    469 
    470 		this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
    471 	}
    472 }
    473 
    474 class RandomGroup : public TestCaseGroup
    475 {
    476 public:
    477 									RandomGroup		(Context& context, const char* name, const char* descr);
    478 									~RandomGroup	(void);
    479 
    480 	void							init			(void);
    481 };
    482 
    483 template <int SIZE>
    484 struct UniformWeightArray
    485 {
    486 	float weights[SIZE];
    487 
    488 	UniformWeightArray (void)
    489 	{
    490 		for (int i=0; i<SIZE; ++i)
    491 			weights[i] = 1.0f;
    492 	}
    493 };
    494 
    495 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
    496 	: TestCaseGroup	(context, name, descr)
    497 {
    498 }
    499 
    500 RandomGroup::~RandomGroup (void)
    501 {
    502 }
    503 
    504 void RandomGroup::init (void)
    505 {
    506 	const int			numAttempts				= 100;
    507 
    508 	static const int	attribCounts[]			= { 1, 2, 5 };
    509 	static const float	attribWeights[]			= { 30, 10, 1 };
    510 	static const int	primitiveCounts[]		= { 1, 5, 64 };
    511 	static const float	primitiveCountWeights[]	= { 20, 10, 1 };
    512 	static const int	indexOffsets[]			= { 0, 7, 13 };
    513 	static const float	indexOffsetWeights[]	= { 20, 20, 1 };
    514 	static const int	firsts[]				= { 0, 7, 13 };
    515 	static const float	firstWeights[]			= { 20, 20, 1 };
    516 	static const int	offsets[]				= { 0, 1, 5, 12 };
    517 	static const float	offsetWeights[]			= { 50, 10, 10, 10 };
    518 	static const int	strides[]				= { 0, 7, 16, 17 };
    519 	static const float	strideWeights[]			= { 50, 10, 10, 10 };
    520 
    521 	static const gls::DrawTestSpec::Primitive primitives[] =
    522 	{
    523 		gls::DrawTestSpec::PRIMITIVE_POINTS,
    524 		gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
    525 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
    526 		gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
    527 		gls::DrawTestSpec::PRIMITIVE_LINES,
    528 		gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
    529 		gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
    530 	};
    531 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
    532 
    533 	static const gls::DrawTestSpec::DrawMethod drawMethods[] =
    534 	{
    535 		gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
    536 		gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
    537 	};
    538 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
    539 
    540 	static const gls::DrawTestSpec::IndexType indexTypes[] =
    541 	{
    542 		gls::DrawTestSpec::INDEXTYPE_BYTE,
    543 		gls::DrawTestSpec::INDEXTYPE_SHORT,
    544 	};
    545 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
    546 
    547 	static const gls::DrawTestSpec::Storage storages[] =
    548 	{
    549 		gls::DrawTestSpec::STORAGE_USER,
    550 		gls::DrawTestSpec::STORAGE_BUFFER,
    551 	};
    552 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(storages)> storageWeights;
    553 
    554 	static const gls::DrawTestSpec::InputType inputTypes[] =
    555 	{
    556 		gls::DrawTestSpec::INPUTTYPE_FLOAT,
    557 		gls::DrawTestSpec::INPUTTYPE_FIXED,
    558 		gls::DrawTestSpec::INPUTTYPE_BYTE,
    559 		gls::DrawTestSpec::INPUTTYPE_SHORT,
    560 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
    561 		gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT
    562 	};
    563 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
    564 
    565 	static const gls::DrawTestSpec::OutputType outputTypes[] =
    566 	{
    567 		gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
    568 		gls::DrawTestSpec::OUTPUTTYPE_VEC2,
    569 		gls::DrawTestSpec::OUTPUTTYPE_VEC3,
    570 		gls::DrawTestSpec::OUTPUTTYPE_VEC4,
    571 	};
    572 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
    573 
    574 	static const gls::DrawTestSpec::Usage usages[] =
    575 	{
    576 		gls::DrawTestSpec::USAGE_STATIC_DRAW,
    577 		gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
    578 		gls::DrawTestSpec::USAGE_STREAM_DRAW,
    579 	};
    580 	const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
    581 
    582 	static const deUint32 blacklistedCases[]=
    583 	{
    584 		3153,	//!< extremely narrow triangle, results depend on sample positions
    585 	};
    586 
    587 	std::set<deUint32>	insertedHashes;
    588 	size_t				insertedCount = 0;
    589 
    590 	for (int ndx = 0; ndx < numAttempts; ++ndx)
    591 	{
    592 		de::Random random(0xc551393 + ndx); // random does not depend on previous cases
    593 
    594 		int					attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
    595 		gls::DrawTestSpec	spec;
    596 
    597 		spec.apiType				= glu::ApiType::es(2,0);
    598 		spec.primitive				= random.chooseWeighted<gls::DrawTestSpec::Primitive>	(DE_ARRAY_BEGIN(primitives),		DE_ARRAY_END(primitives),		primitiveWeights.weights);
    599 		spec.primitiveCount			= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(primitiveCounts),	DE_ARRAY_END(primitiveCounts),	primitiveCountWeights);
    600 		spec.drawMethod				= random.chooseWeighted<gls::DrawTestSpec::DrawMethod>	(DE_ARRAY_BEGIN(drawMethods),		DE_ARRAY_END(drawMethods),		drawMethodWeights.weights);
    601 		spec.indexType				= random.chooseWeighted<gls::DrawTestSpec::IndexType>	(DE_ARRAY_BEGIN(indexTypes),		DE_ARRAY_END(indexTypes),		indexTypeWeights.weights);
    602 		spec.indexPointerOffset		= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(indexOffsets),		DE_ARRAY_END(indexOffsets),		indexOffsetWeights);
    603 		spec.indexStorage			= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
    604 		spec.first					= random.chooseWeighted<int, const int*, const float*>	(DE_ARRAY_BEGIN(firsts),			DE_ARRAY_END(firsts),			firstWeights);
    605 		spec.indexMin				= 0;
    606 		spec.indexMax				= 0;
    607 		spec.instanceCount			= 0;
    608 
    609 		// check spec is legal
    610 		if (!spec.valid())
    611 			continue;
    612 
    613 		for (int attrNdx = 0; attrNdx < attributeCount;)
    614 		{
    615 			bool valid;
    616 			gls::DrawTestSpec::AttributeSpec attribSpec;
    617 
    618 			attribSpec.inputType			= random.chooseWeighted<gls::DrawTestSpec::InputType>	(DE_ARRAY_BEGIN(inputTypes),		DE_ARRAY_END(inputTypes),		inputTypeWeights.weights);
    619 			attribSpec.outputType			= random.chooseWeighted<gls::DrawTestSpec::OutputType>	(DE_ARRAY_BEGIN(outputTypes),		DE_ARRAY_END(outputTypes),		outputTypeWeights.weights);
    620 			attribSpec.storage				= random.chooseWeighted<gls::DrawTestSpec::Storage>		(DE_ARRAY_BEGIN(storages),			DE_ARRAY_END(storages),			storageWeights.weights);
    621 			attribSpec.usage				= random.chooseWeighted<gls::DrawTestSpec::Usage>		(DE_ARRAY_BEGIN(usages),			DE_ARRAY_END(usages),			usageWeights.weights);
    622 			attribSpec.componentCount		= random.getInt(1, 4);
    623 			attribSpec.offset				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
    624 			attribSpec.stride				= random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
    625 			attribSpec.normalize			= random.getBool();
    626 			attribSpec.instanceDivisor		= 0;
    627 			attribSpec.useDefaultAttribute	= random.getBool();
    628 
    629 			// check spec is legal
    630 			valid = attribSpec.valid(spec.apiType);
    631 
    632 			// we do not want interleaved elements. (Might result in some weird floating point values)
    633 			if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
    634 				valid = false;
    635 
    636 			// try again if not valid
    637 			if (valid)
    638 			{
    639 				spec.attribs.push_back(attribSpec);
    640 				++attrNdx;
    641 			}
    642 		}
    643 
    644 		// Do not collapse all vertex positions to a single positions
    645 		if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    646 			spec.attribs[0].instanceDivisor = 0;
    647 
    648 		// Is render result meaningful?
    649 		{
    650 			// Only one vertex
    651 			if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    652 				continue;
    653 			if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
    654 				continue;
    655 
    656 			// Triangle only on one axis
    657 			if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
    658 			{
    659 				if (spec.attribs[0].componentCount == 1)
    660 					continue;
    661 				if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
    662 					continue;
    663 				if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
    664 					continue;
    665 			}
    666 		}
    667 
    668 		// Add case
    669 		{
    670 			deUint32 hash = spec.hash();
    671 			for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
    672 				hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
    673 
    674 			if (insertedHashes.find(hash) == insertedHashes.end() &&
    675 				!de::contains(DE_ARRAY_BEGIN(blacklistedCases), DE_ARRAY_END(blacklistedCases), hash))
    676 			{
    677 				// Only aligned cases
    678 				if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
    679 					spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
    680 					this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
    681 				insertedHashes.insert(hash);
    682 
    683 				++insertedCount;
    684 			}
    685 		}
    686 	}
    687 }
    688 
    689 } // anonymous
    690 
    691 DrawTests::DrawTests (Context& context)
    692 	: TestCaseGroup(context, "draw", "Drawing tests")
    693 {
    694 }
    695 
    696 DrawTests::~DrawTests (void)
    697 {
    698 }
    699 
    700 void DrawTests::init (void)
    701 {
    702 	// Basic
    703 	{
    704 		const gls::DrawTestSpec::DrawMethod basicMethods[] =
    705 		{
    706 			gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS,
    707 			gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS,
    708 		};
    709 
    710 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
    711 		{
    712 			std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
    713 			std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
    714 
    715 			this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
    716 		}
    717 	}
    718 
    719 	// Random
    720 
    721 	this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
    722 }
    723 
    724 } // Functional
    725 } // gles2
    726 } // deqp
    727