13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program OpenGL ES 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 Shader variable type utilities.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gluVarTypeUtil.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <stdlib.h>
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace glu
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// VarTokenizer
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko PoyryVarTokenizer::VarTokenizer (const char* str)
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_str			(str)
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_token		(TOKEN_LAST)
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_tokenStart	(0)
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_tokenLen	(0)
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	advance();
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint VarTokenizer::getNumber (void) const
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return atoi(getIdentifier().c_str());
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool	isNum				(char c) { return de::inRange(c, '0', '9'); }
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool	isAlpha				(char c) { return de::inRange(c, 'a', 'z') || de::inRange(c, 'A', 'Z');	}
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool	isIdentifierChar	(char c) { return isAlpha(c) || isNum(c) || c == '_'; }
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid VarTokenizer::advance (void)
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_token != TOKEN_END);
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_tokenStart	+= m_tokenLen;
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_token			 = TOKEN_LAST;
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_tokenLen		 = 1;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_str[m_tokenStart] == '[')
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_token = TOKEN_LEFT_BRACKET;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_str[m_tokenStart] == ']')
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_token = TOKEN_RIGHT_BRACKET;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_str[m_tokenStart] == 0)
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_token = TOKEN_END;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (m_str[m_tokenStart] == '.')
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_token = TOKEN_PERIOD;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isNum(m_str[m_tokenStart]))
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_token = TOKEN_NUMBER;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (isNum(m_str[m_tokenStart+m_tokenLen]))
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_tokenLen += 1;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (isIdentifierChar(m_str[m_tokenStart]))
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_token = TOKEN_IDENTIFIER;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (isIdentifierChar(m_str[m_tokenStart+m_tokenLen]))
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_tokenLen += 1;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		TCU_FAIL("Unexpected character");
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// SubTypeAccess
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySubTypeAccess::SubTypeAccess (const VarType& type)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_type(type)
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::string parseVariableName (const char* nameWithPath)
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VarTokenizer tokenizer(nameWithPath);
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return tokenizer.getIdentifier();
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid parseTypePath (const char* nameWithPath, const VarType& type, TypeComponentVector& path)
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	VarTokenizer tokenizer(nameWithPath);
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER)
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tokenizer.advance();
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	path.clear();
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (tokenizer.getToken() != VarTokenizer::TOKEN_END)
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		VarType curType = getVarType(type, path);
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (tokenizer.getToken() == VarTokenizer::TOKEN_PERIOD)
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tokenizer.advance();
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK_MSG(curType.isStructType(), "Invalid field selector");
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Find member.
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			std::string		memberName	= tokenizer.getIdentifier();
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int				ndx			= 0;
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			for (; ndx < curType.getStructPtr()->getNumMembers(); ndx++)
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (memberName == curType.getStructPtr()->getMember(ndx).getName())
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					break;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK_MSG(ndx < curType.getStructPtr()->getNumMembers(), "Member not found in type");
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, ndx));
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tokenizer.advance();
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else if (tokenizer.getToken() == VarTokenizer::TOKEN_LEFT_BRACKET)
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tokenizer.advance();
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_NUMBER);
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			int ndx = tokenizer.getNumber();
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curType.isArrayType())
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_CHECK(de::inBounds(ndx, 0, curType.getArraySize()));
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, ndx));
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (curType.isBasicType() && isDataTypeMatrix(curType.getBasicType()))
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_CHECK(de::inBounds(ndx, 0, getDataTypeMatrixNumColumns(curType.getBasicType())));
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, ndx));
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (curType.isBasicType() && isDataTypeVector(curType.getBasicType()))
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_CHECK(de::inBounds(ndx, 0, getDataTypeScalarSize(curType.getBasicType())));
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, ndx));
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				TCU_FAIL("Invalid subscript");
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tokenizer.advance();
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_RIGHT_BRACKET);
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			tokenizer.advance();
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			TCU_FAIL("Unexpected token");
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystd::ostream& operator<< (std::ostream& str, const TypeAccessFormat& format)
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const VarType* curType = &format.type;
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (TypeComponentVector::const_iterator iter = format.path.begin(); iter != format.path.end(); iter++)
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (iter->type)
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case VarTypeComponent::ARRAY_ELEMENT:
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curType = &curType->getElementType(); // Update current type.
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Fall-through.
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case VarTypeComponent::MATRIX_COLUMN:
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case VarTypeComponent::VECTOR_COMPONENT:
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				str << "[" << iter->index << "]";
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case VarTypeComponent::STRUCT_MEMBER:
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				const StructMember& member = curType->getStructPtr()->getMember(iter->index);
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				str << "." << member.getName();
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				curType = &member.getType();
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return str;
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // glu
196