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