13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL Utilities
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ---------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Draw call utilities.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluDrawUtil.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluRenderContext.hpp"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluObjectWrapper.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwFunctions.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "glwEnums.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <set>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <iterator>
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace glu
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VertexAttributeDescriptor
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							location;
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexComponentType			componentType;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexComponentConversion	convert;
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							numComponents;
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							numElements;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int							stride;				//!< Stride or 0 if using default stride.
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const void*					pointer;			//!< Pointer or offset.
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexAttributeDescriptor (int							location_,
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   VertexComponentType			componentType_,
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   VertexComponentConversion	convert_,
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   int							numComponents_,
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   int							numElements_,
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   int							stride_,
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							   const void*					pointer_)
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: location		(location_)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, componentType	(componentType_)
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, convert		(convert_)
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, numComponents	(numComponents_)
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, numElements	(numElements_)
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, stride		(stride_)
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, pointer		(pointer_)
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexAttributeDescriptor (void)
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: location		(0)
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, componentType	(VTX_COMP_TYPE_LAST)
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, convert		(VTX_COMP_CONVERT_LAST)
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, numComponents	(0)
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, numElements	(0)
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, stride		(0)
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		, pointer		(0)
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VertexBufferLayout
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int										size;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VertexAttributeDescriptor>	attributes;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexBufferLayout (int size_ = 0)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: size(size_)
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct VertexBufferDescriptor
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32								buffer;
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VertexAttributeDescriptor>	attributes;
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexBufferDescriptor (deUint32 buffer_ = 0)
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		: buffer(buffer_)
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass VertexBuffer : public Buffer
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum Type
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TYPE_PLANAR = 0,	//!< Data for each vertex array resides in a separate contiguous block in buffer.
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TYPE_STRIDED,		//!< Vertex arrays are interleaved.
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TYPE_LAST
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									VertexBuffer		(const RenderContext& context, int numBindings, const VertexArrayBinding* bindings, Type type = TYPE_PLANAR);
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									~VertexBuffer		(void);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VertexBufferDescriptor&	getDescriptor		(void) const { return m_layout; }
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									VertexBuffer		(const VertexBuffer& other);
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexBuffer&					operator=			(const VertexBuffer& other);
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexBufferDescriptor			m_layout;
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass IndexBuffer : public Buffer
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									IndexBuffer			(const RenderContext& context, IndexType indexType, int numIndices, const void* indices);
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									~IndexBuffer		(void);
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									IndexBuffer			(const IndexBuffer& other);
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	IndexBuffer&					operator=			(const IndexBuffer& other);
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getVtxCompGLType (VertexComponentType type)
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_UNSIGNED_INT8:	return GL_UNSIGNED_BYTE;
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_UNSIGNED_INT16:	return GL_UNSIGNED_SHORT;
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_UNSIGNED_INT32:	return GL_UNSIGNED_INT;
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_SIGNED_INT8:		return GL_BYTE;
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_SIGNED_INT16:		return GL_SHORT;
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_SIGNED_INT32:		return GL_INT;
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_FIXED:			return GL_FIXED;
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_HALF_FLOAT:		return GL_HALF_FLOAT;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_FLOAT:			return GL_FLOAT;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return GL_NONE;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getVtxCompSize (VertexComponentType type)
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_UNSIGNED_INT8:	return 1;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_UNSIGNED_INT16:	return 2;
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_UNSIGNED_INT32:	return 4;
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_SIGNED_INT8:		return 1;
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_SIGNED_INT16:		return 2;
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_SIGNED_INT32:		return 4;
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_FIXED:			return 4;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_HALF_FLOAT:		return 2;
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case VTX_COMP_FLOAT:			return 4;
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getIndexGLType (IndexType type)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT8:	return GL_UNSIGNED_BYTE;
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT16:	return GL_UNSIGNED_SHORT;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT32:	return GL_UNSIGNED_INT;
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getIndexSize (IndexType type)
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT8:	return 1;
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT16:	return 2;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case INDEXTYPE_UINT32:	return 4;
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getPrimitiveGLType (PrimitiveType type)
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (type)
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_TRIANGLES:		return GL_TRIANGLES;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_TRIANGLE_STRIP:	return GL_TRIANGLE_STRIP;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_TRIANGLE_FAN:	return GL_TRIANGLE_FAN;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_LINES:			return GL_LINES;
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_LINE_STRIP:		return GL_LINE_STRIP;
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_LINE_LOOP:		return GL_LINE_LOOP;
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_POINTS:			return GL_POINTS;
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		case PRIMITIVETYPE_PATCHES:			return GL_PATCHES;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		default:
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(false);
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return 0;
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Lower named bindings to locations and eliminate bindings that are not used by program.
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename InputIter, typename OutputIter>
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic OutputIter namedBindingsToProgramLocations (const glw::Functions& gl, deUint32 program, InputIter first, InputIter end, OutputIter out)
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (InputIter cur = first; cur != end; ++cur)
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BindingPoint& binding = cur->binding;
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (binding.type == BindingPoint::TYPE_NAME)
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(binding.location >= 0);
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int location = gl.getAttribLocation(program, binding.name.c_str());
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (location >= 0)
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Add binding.location as an offset to accommodate matrices.
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				*out = VertexArrayBinding(BindingPoint(location + binding.location), cur->pointer);
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				++out;
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			*out = *cur;
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			++out;
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return out;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic deUint32 getMinimumAlignment (const VertexArrayPointer& pointer)
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2013-05-07 pyry] What is the actual min?
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(pointer);
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (deUint32)sizeof(float);
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename BindingIter>
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool areVertexArrayLocationsValid (BindingIter first, BindingIter end)
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::set<int> usedLocations;
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (BindingIter cur = first; cur != end; ++cur)
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const BindingPoint& binding = cur->binding;
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (binding.type != BindingPoint::TYPE_LOCATION)
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (usedLocations.find(binding.location) != usedLocations.end())
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return false;
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		usedLocations.insert(binding.location);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// \todo [2013-05-08 pyry] Buffer upload should try to match pointers to reduce dataset size.
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void appendAttributeNonStrided (VertexBufferLayout& layout, const VertexArrayBinding& va)
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	offset		= deAlign32(layout.size, getMinimumAlignment(va.pointer));
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	elementSize	= getVtxCompSize(va.pointer.componentType)*va.pointer.numComponents;
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	size		= elementSize*va.pointer.numElements;
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Must be assigned to location at this point.
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(va.binding.type == BindingPoint::TYPE_LOCATION);
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	layout.attributes.push_back(VertexAttributeDescriptor(va.binding.location,
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  va.pointer.componentType,
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  va.pointer.convert,
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  va.pointer.numComponents,
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  va.pointer.numElements,
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  0, // default stride
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry														  (const void*)(deUintptr)offset));
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	layout.size = offset+size;
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytemplate<typename BindingIter>
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void computeNonStridedBufferLayout (VertexBufferLayout& layout, BindingIter first, BindingIter end)
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (BindingIter iter = first; iter != end; ++iter)
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		appendAttributeNonStrided(layout, *iter);
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void copyToLayout (void* dstBasePtr, const VertexAttributeDescriptor& dstVA, const VertexArrayPointer& srcPtr)
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(dstVA.componentType	== srcPtr.componentType &&
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  dstVA.numComponents	== srcPtr.numComponents &&
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  dstVA.numElements		== srcPtr.numElements);
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const int	elementSize			= getVtxCompSize(dstVA.componentType)*dstVA.numComponents;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	srcHasCustomStride	= srcPtr.stride != 0 && srcPtr.stride != elementSize;
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool	dstHasCustomStride	= dstVA.stride != 0 && dstVA.stride != elementSize;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (srcHasCustomStride || dstHasCustomStride)
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	dstStride	= dstVA.stride != 0 ? dstVA.stride : elementSize;
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const int	srcStride	= srcPtr.stride != 0 ? srcPtr.stride : elementSize;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < dstVA.numElements; ndx++)
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			deMemcpy((deUint8*)dstBasePtr + (deUintptr)dstVA.pointer + ndx*dstStride, (const deUint8*)srcPtr.data + ndx*srcStride, elementSize);
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		deMemcpy((deUint8*)dstBasePtr + (deUintptr)dstVA.pointer, srcPtr.data, elementSize*dstVA.numElements);
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid uploadBufferData (const glw::Functions& gl, deUint32 buffer, deUint32 usage, const VertexBufferLayout& layout, const VertexArrayPointer* srcArrays)
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create temporary data buffer for upload.
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint8> localBuf(layout.size);
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int attrNdx = 0; attrNdx < (int)layout.attributes.size(); ++attrNdx)
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		copyToLayout(&localBuf[0], layout.attributes[attrNdx], srcArrays[attrNdx]);
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_ARRAY_BUFFER, (int)localBuf.size(), &localBuf[0], usage);
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading buffer data failed");
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// VertexBuffer
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3393c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexBuffer::VertexBuffer (const RenderContext& context, int numBindings, const VertexArrayBinding* bindings, Type type)
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: Buffer(context)
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= context.getFunctions();
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			usage	= GL_STATIC_DRAW;
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexBufferLayout		layout;
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!areVertexArrayLocationsValid(bindings, bindings+numBindings))
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::TestError("Invalid vertex array locations");
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (type == TYPE_PLANAR)
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		computeNonStridedBufferLayout(layout, bindings, bindings+numBindings);
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		throw tcu::InternalError("Strided layout is not yet supported");
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VertexArrayPointer> srcPtrs(numBindings);
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < numBindings; ndx++)
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		srcPtrs[ndx] = bindings[ndx].pointer;
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(srcPtrs.size() == layout.attributes.size());
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!srcPtrs.empty())
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		uploadBufferData(gl, m_object, usage, layout, &srcPtrs[0]);
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Construct descriptor.
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_layout.buffer		= m_object;
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_layout.attributes	= layout.attributes;
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3673c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVertexBuffer::~VertexBuffer (void)
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// IndexBuffer
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIndexBuffer::IndexBuffer (const RenderContext& context, IndexType indexType, int numIndices, const void* indices)
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: Buffer(context)
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= context.getFunctions();
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32			usage	= GL_STATIC_DRAW;
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_object);
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*getIndexSize(indexType), indices, usage);
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(gl.getError(), "Uploading index data failed");
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3853c827367444ee418f129b2c238299f49d3264554Jarkko PoyryIndexBuffer::~IndexBuffer (void)
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline VertexAttributeDescriptor getUserPointerDescriptor (const VertexArrayBinding& vertexArray)
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(vertexArray.binding.type == BindingPoint::TYPE_LOCATION);
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return VertexAttributeDescriptor(vertexArray.binding.location,
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 vertexArray.pointer.componentType,
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 vertexArray.pointer.convert,
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 vertexArray.pointer.numComponents,
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 vertexArray.pointer.numElements,
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 vertexArray.pointer.stride,
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry									 vertexArray.pointer.data);
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Setup VA according to allocation spec. Assumes that other state (VAO binding, buffer) is set already.
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void setVertexAttribPointer (const glw::Functions& gl, const VertexAttributeDescriptor& va)
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		isIntType		= de::inRange<int>(va.componentType, VTX_COMP_UNSIGNED_INT8, VTX_COMP_SIGNED_INT32);
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const bool		isSpecialType	= de::inRange<int>(va.componentType, VTX_COMP_FIXED, VTX_COMP_FLOAT);
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint32	compTypeGL		= getVtxCompGLType(va.componentType);
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isIntType != isSpecialType); // Must be either int or special type.
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isIntType || va.convert == VTX_COMP_CONVERT_NONE); // Conversion allowed only for special types.
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(isSpecialType);
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.enableVertexAttribArray(va.location);
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isIntType && va.convert == VTX_COMP_CONVERT_NONE)
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.vertexAttribIPointer(va.location, va.numComponents, compTypeGL, va.stride, va.pointer);
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.vertexAttribPointer(va.location, va.numComponents, compTypeGL, va.convert == VTX_COMP_CONVERT_NORMALIZE_TO_FLOAT ? GL_TRUE : GL_FALSE, va.stride, va.pointer);
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//! Setup vertex buffer and attributes.
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void setVertexBufferAttributes (const glw::Functions& gl, const VertexBufferDescriptor& buffer)
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ARRAY_BUFFER, buffer.buffer);
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<VertexAttributeDescriptor>::const_iterator vaIter = buffer.attributes.begin(); vaIter != buffer.attributes.end(); ++vaIter)
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setVertexAttribPointer(gl, *vaIter);
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void disableVertexArrays (const glw::Functions& gl, const std::vector<VertexArrayBinding>& bindings)
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindings.begin(); vaIter != bindings.end(); ++vaIter)
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(vaIter->binding.type == BindingPoint::TYPE_LOCATION);
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.disableVertexAttribArray(vaIter->binding.location);
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(DE_DEBUG)
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isProgramActive (const RenderContext& context, deUint32 program)
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2013-05-08 pyry] Is this query broken?
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*	deUint32 activeProgram = 0;
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	context.getFunctions().getIntegerv(GL_ACTIVE_PROGRAM, (int*)&activeProgram);
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	GLU_EXPECT_NO_ERROR(context.getFunctions().getError(), "oh");
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return activeProgram == program;*/
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(context);
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_UNREF(program);
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic bool isDrawCallValid (int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives)
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (numVertexArrays < 0)
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((primitives.indexType == INDEXTYPE_LAST) != (primitives.indices == 0))
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (primitives.numElements < 0)
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return false;
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!primitives.indices)
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		for (int ndx = 0; ndx < numVertexArrays; ndx++)
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (primitives.numElements > vertexArrays[ndx].pointer.numElements)
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return false;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [2013-05-08 pyry] We could walk whole index array and determine index range
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return true;
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif // DE_DEBUG
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void drawNonIndexed (const glw::Functions& gl, PrimitiveType type, int numElements)
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32 mode = getPrimitiveGLType(type);
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.drawArrays(mode, 0, numElements);
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline void drawIndexed (const glw::Functions& gl, PrimitiveType type, int numElements, IndexType indexType, const void* indexPtr)
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32	mode		= getPrimitiveGLType(type);
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint32	indexGLType	= getIndexGLType(indexType);
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.drawElements(mode, numElements, indexGLType, indexPtr);
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // anonymous
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid drawFromUserPointers (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&				gl		= context.getFunctions();
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VertexArrayBinding>		bindingsWithLocations;
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isDrawCallValid(numVertexArrays, vertexArrays, primitives));
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isProgramActive(context, program));
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Lower bindings to locations.
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	namedBindingsToProgramLocations(gl, program, vertexArrays, vertexArrays+numVertexArrays, std::inserter(bindingsWithLocations, bindingsWithLocations.begin()));
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(areVertexArrayLocationsValid(bindingsWithLocations.begin(), bindingsWithLocations.end()));
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Set VA state.
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindingsWithLocations.begin(); vaIter != bindingsWithLocations.end(); ++vaIter)
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setVertexAttribPointer(gl, getUserPointerDescriptor(*vaIter));
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (callback)
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		callback->beforeDrawCall();
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (primitives.indices)
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawIndexed(gl, primitives.type, primitives.numElements, primitives.indexType, primitives.indices);
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawNonIndexed(gl, primitives.type, primitives.numElements);
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (callback)
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		callback->afterDrawCall();
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Disable attribute arrays or otherwise someone later on might get crash thanks to invalid pointers.
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	disableVertexArrays(gl, bindingsWithLocations);
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid drawFromBuffers (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&				gl		= context.getFunctions();
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<VertexArrayBinding>		bindingsWithLocations;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isDrawCallValid(numVertexArrays, vertexArrays, primitives));
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(isProgramActive(context, program));
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Lower bindings to locations.
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	namedBindingsToProgramLocations(gl, program, vertexArrays, vertexArrays+numVertexArrays, std::inserter(bindingsWithLocations, bindingsWithLocations.begin()));
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(areVertexArrayLocationsValid(bindingsWithLocations.begin(), bindingsWithLocations.end()));
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Create buffers for duration of draw call.
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VertexBuffer vertexBuffer (context, (int)bindingsWithLocations.size(), (bindingsWithLocations.empty()) ? (DE_NULL) : (&bindingsWithLocations[0]));
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Set state.
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		setVertexBufferAttributes(gl, vertexBuffer.getDescriptor());
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (primitives.indices)
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			IndexBuffer indexBuffer(context, primitives.indexType, primitives.numElements, primitives.indices);
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *indexBuffer);
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (callback)
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				callback->beforeDrawCall();
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			drawIndexed(gl, primitives.type, primitives.numElements, primitives.indexType, 0);
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (callback)
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				callback->afterDrawCall();
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (callback)
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				callback->beforeDrawCall();
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			drawNonIndexed(gl, primitives.type, primitives.numElements);
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (callback)
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				callback->afterDrawCall();
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Disable attribute arrays or otherwise someone later on might get crash thanks to invalid pointers.
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (std::vector<VertexArrayBinding>::const_iterator vaIter = bindingsWithLocations.begin(); vaIter != bindingsWithLocations.end(); ++vaIter)
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		gl.disableVertexAttribArray(vaIter->binding.location);
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid drawFromVAOBuffers (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glw::Functions&	gl		= context.getFunctions();
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VertexArray				vao		(context);
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(*vao);
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	drawFromBuffers(context, program, numVertexArrays, vertexArrays, primitives, callback);
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	gl.bindVertexArray(0);
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid draw (const RenderContext& context, deUint32 program, int numVertexArrays, const VertexArrayBinding* vertexArrays, const PrimitiveList& primitives, DrawUtilCallback* callback)
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const glu::ContextType ctxType = context.getType();
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (isContextTypeGLCore(ctxType) || contextSupports(ctxType, ApiType::es(3,1)))
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawFromVAOBuffers(context, program, numVertexArrays, vertexArrays, primitives, callback);
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(isContextTypeES(ctxType));
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		drawFromUserPointers(context, program, numVertexArrays, vertexArrays, primitives, callback);
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // glu
604