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