Home | History | Annotate | Download | only in opengl
      1 #ifndef _GLUVARTYPEUTIL_HPP
      2 #define _GLUVARTYPEUTIL_HPP
      3 /*-------------------------------------------------------------------------
      4  * drawElements Quality Program OpenGL ES Utilities
      5  * ------------------------------------------------
      6  *
      7  * Copyright 2014 The Android Open Source Project
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief Shader variable type utilities.
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "tcuDefs.hpp"
     27 #include "gluVarType.hpp"
     28 
     29 #include <vector>
     30 #include <string>
     31 #include <iterator>
     32 
     33 namespace glu
     34 {
     35 
     36 // Variable path tokenizer
     37 
     38 class VarTokenizer
     39 {
     40 public:
     41 	enum Token
     42 	{
     43 		TOKEN_IDENTIFIER = 0,
     44 		TOKEN_LEFT_BRACKET,
     45 		TOKEN_RIGHT_BRACKET,
     46 		TOKEN_PERIOD,
     47 		TOKEN_NUMBER,
     48 		TOKEN_END,
     49 
     50 		TOKEN_LAST
     51 	};
     52 
     53 					VarTokenizer					(const char* str);
     54 					~VarTokenizer					(void) {}
     55 
     56 	Token			getToken						(void) const { return m_token;															}
     57 	std::string		getIdentifier					(void) const { return std::string(m_str+m_tokenStart, m_str+m_tokenStart+m_tokenLen);	}
     58 	int				getNumber						(void) const;
     59 	int				getCurrentTokenStartLocation	(void) const { return m_tokenStart;														}
     60 	int				getCurrentTokenEndLocation		(void) const { return m_tokenStart + m_tokenLen;										}
     61 	void			advance							(void);
     62 
     63 private:
     64 	const char*		m_str;
     65 
     66 	Token			m_token;
     67 	int				m_tokenStart;
     68 	int				m_tokenLen;
     69 };
     70 
     71 // VarType subtype path utilities.
     72 
     73 struct VarTypeComponent
     74 {
     75 	enum Type
     76 	{
     77 		STRUCT_MEMBER = 0,
     78 		ARRAY_ELEMENT,
     79 		MATRIX_COLUMN,
     80 		VECTOR_COMPONENT,
     81 
     82 		TYPE_LAST
     83 	};
     84 
     85 				VarTypeComponent	(Type type_, int index_)	: type(type_), index(index_) {}
     86 				VarTypeComponent	(void)						: type(TYPE_LAST), index(0) {}
     87 
     88 	bool		operator==			(const VarTypeComponent& other) const { return type == other.type && index == other.index; }
     89 	bool		operator!=			(const VarTypeComponent& other) const { return type != other.type || index != other.index; }
     90 
     91 	Type		type;
     92 	int			index;
     93 };
     94 
     95 typedef std::vector<VarTypeComponent> TypeComponentVector;
     96 
     97 // TypeComponentVector utilties.
     98 
     99 template <typename Iterator>
    100 bool			isValidTypePath		(const VarType& type, Iterator begin, Iterator end);
    101 
    102 template <typename Iterator>
    103 VarType			getVarType			(const VarType& type, Iterator begin, Iterator end);
    104 
    105 inline bool		isValidTypePath		(const VarType& type, const TypeComponentVector& path) { return isValidTypePath(type, path.begin(), path.end()); }
    106 inline VarType	getVarType			(const VarType& type, const TypeComponentVector& path) { return getVarType(type, path.begin(), path.end()); }
    107 
    108 std::string		parseVariableName	(const char* nameWithPath);
    109 void			parseTypePath		(const char* nameWithPath, const VarType& type, TypeComponentVector& path);
    110 
    111 // Type path formatter.
    112 
    113 struct TypeAccessFormat
    114 {
    115 	TypeAccessFormat (const VarType& type_, const TypeComponentVector& path_) : type(type_), path(path_) {}
    116 
    117 	const VarType&					type;
    118 	const TypeComponentVector&		path;
    119 };
    120 
    121 std::ostream&		operator<<		(std::ostream& str, const TypeAccessFormat& format);
    122 
    123 // Subtype path builder.
    124 
    125 class SubTypeAccess
    126 {
    127 public:
    128 								SubTypeAccess		(const VarType& type);
    129 
    130 	SubTypeAccess&				member				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access struct element.
    131 	SubTypeAccess&				element				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access array element.
    132 	SubTypeAccess&				column				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access column.
    133 	SubTypeAccess&				component			(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access component.
    134 	SubTypeAccess&				parent				(void)		{ DE_ASSERT(!m_path.empty()); m_path.pop_back(); return *this; }
    135 
    136 	SubTypeAccess				member				(int ndx) const { return SubTypeAccess(*this).member(ndx);		}
    137 	SubTypeAccess				element				(int ndx) const { return SubTypeAccess(*this).element(ndx);		}
    138 	SubTypeAccess				column				(int ndx) const { return SubTypeAccess(*this).column(ndx);		}
    139 	SubTypeAccess				component			(int ndx) const { return SubTypeAccess(*this).component(ndx);	}
    140 	SubTypeAccess				parent				(void) const	{ return SubTypeAccess(*this).parent();			}
    141 
    142 	bool						isValid				(void) const	{ return isValidTypePath(m_type, m_path);		}
    143 	VarType						getType				(void) const	{ return getVarType(m_type, m_path);			}
    144 	const TypeComponentVector&	getPath				(void) const	{ return m_path;								}
    145 
    146 	bool						empty				(void) const { return m_path.empty(); }
    147 
    148 	bool						operator==			(const SubTypeAccess& other) const { return m_path == other.m_path && m_type == other.m_type; }
    149 	bool						operator!=			(const SubTypeAccess& other) const { return m_path != other.m_path || m_type != other.m_type; }
    150 
    151 private:
    152 	VarType						m_type;
    153 	TypeComponentVector			m_path;
    154 };
    155 
    156 // Subtype iterator.
    157 
    158 // \note VarType must be live during iterator usage.
    159 template <class IsExpanded>
    160 class SubTypeIterator : public std::iterator<std::forward_iterator_tag, VarType>
    161 {
    162 public:
    163 	static SubTypeIterator<IsExpanded>	begin				(const VarType* type) { return SubTypeIterator(type);						}
    164 	static SubTypeIterator<IsExpanded>	end					(const VarType* type) { DE_UNREF(type); return SubTypeIterator(DE_NULL);	}
    165 
    166 	bool								operator==			(const SubTypeIterator<IsExpanded>& other) const { return m_type == other.m_type && m_path == other.m_path; }
    167 	bool								operator!=			(const SubTypeIterator<IsExpanded>& other) const { return m_type != other.m_type || m_path != other.m_path; }
    168 
    169 	SubTypeIterator<IsExpanded>&		operator++			(void);
    170 	SubTypeIterator<IsExpanded>			operator++			(int)	{ SubTypeIterator<IsExpanded> copy(*this); ++(*this); return copy; }
    171 
    172 	void								toStream			(std::ostream& str) const { str << TypeAccessFormat(*m_type, m_path); }
    173 	VarType								getType				(void) const { return getVarType(*m_type, m_path.begin(), m_path.end()); }
    174 	const TypeComponentVector&			getPath				(void) const { return m_path; }
    175 
    176 	VarType								operator*			(void) const { return getType(); }
    177 
    178 private:
    179 										SubTypeIterator		(const VarType* type);
    180 
    181 	void								removeTraversed		(void);
    182 	void								findNext			(void);
    183 
    184 	const VarType*						m_type;
    185 	TypeComponentVector					m_path;
    186 };
    187 
    188 struct IsBasicType			{ bool operator() (const VarType& type) const { return type.isBasicType(); } };
    189 struct IsScalarType			{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalar(type.getBasicType()); } };
    190 struct IsVectorOrScalarType	{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalarOrVector(type.getBasicType()); } };
    191 
    192 typedef SubTypeIterator<IsBasicType>			BasicTypeIterator;
    193 typedef SubTypeIterator<IsVectorOrScalarType>	VectorTypeIterator;
    194 typedef SubTypeIterator<IsScalarType>			ScalarTypeIterator;
    195 
    196 template <class IsExpanded>
    197 std::ostream& operator<< (std::ostream& str, const SubTypeIterator<IsExpanded>& iter)
    198 {
    199 	iter.toStream(str);
    200 	return str;
    201 }
    202 
    203 template <class IsExpanded>
    204 SubTypeIterator<IsExpanded>::SubTypeIterator (const VarType* type)
    205 	: m_type(type)
    206 {
    207 	if (m_type)
    208 		findNext();
    209 }
    210 
    211 template <class IsExpanded>
    212 SubTypeIterator<IsExpanded>& SubTypeIterator<IsExpanded>::operator++ (void)
    213 {
    214 	if (!m_path.empty())
    215 	{
    216 		// Remove traversed nodes.
    217 		removeTraversed();
    218 
    219 		if (!m_path.empty())
    220 			findNext();
    221 		else
    222 			m_type = DE_NULL; // Unset type to signal end.
    223 	}
    224 	else
    225 	{
    226 		// First type was already expanded.
    227 		DE_ASSERT(IsExpanded()(getVarType(*m_type, m_path)));
    228 		m_type = DE_NULL;
    229 	}
    230 
    231 	return *this;
    232 }
    233 
    234 template <class IsExpanded>
    235 void SubTypeIterator<IsExpanded>::removeTraversed (void)
    236 {
    237 	DE_ASSERT(m_type && !m_path.empty());
    238 
    239 	// Pop traversed nodes.
    240 	while (!m_path.empty())
    241 	{
    242 		VarTypeComponent&	curComp		= m_path.back();
    243 		VarType				parentType	= getVarType(*m_type, m_path.begin(), m_path.end()-1);
    244 
    245 		if (curComp.type == VarTypeComponent::MATRIX_COLUMN)
    246 		{
    247 			DE_ASSERT(isDataTypeMatrix(parentType.getBasicType()));
    248 			if (curComp.index+1 < getDataTypeMatrixNumColumns(parentType.getBasicType()))
    249 				break;
    250 		}
    251 		else if (curComp.type == VarTypeComponent::VECTOR_COMPONENT)
    252 		{
    253 			DE_ASSERT(isDataTypeVector(parentType.getBasicType()));
    254 			if (curComp.index+1 < getDataTypeScalarSize(parentType.getBasicType()))
    255 				break;
    256 		}
    257 		else if (curComp.type == VarTypeComponent::ARRAY_ELEMENT)
    258 		{
    259 			DE_ASSERT(parentType.isArrayType());
    260 			if (curComp.index+1 < parentType.getArraySize())
    261 				break;
    262 		}
    263 		else if (curComp.type == VarTypeComponent::STRUCT_MEMBER)
    264 		{
    265 			DE_ASSERT(parentType.isStructType());
    266 			if (curComp.index+1 < parentType.getStructPtr()->getNumMembers())
    267 				break;
    268 		}
    269 
    270 		m_path.pop_back();
    271 	}
    272 }
    273 
    274 template <class IsExpanded>
    275 void SubTypeIterator<IsExpanded>::findNext (void)
    276 {
    277 	if (!m_path.empty())
    278 	{
    279 		// Increment child counter in current level.
    280 		VarTypeComponent& curComp = m_path.back();
    281 		curComp.index += 1;
    282 	}
    283 
    284 	for (;;)
    285 	{
    286 		VarType curType = getVarType(*m_type, m_path);
    287 
    288 		if (IsExpanded()(curType))
    289 			break;
    290 
    291 		// Recurse into child type.
    292 		if (curType.isBasicType())
    293 		{
    294 			DataType basicType = curType.getBasicType();
    295 
    296 			if (isDataTypeMatrix(basicType))
    297 				m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, 0));
    298 			else if (isDataTypeVector(basicType))
    299 				m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, 0));
    300 			else
    301 				DE_ASSERT(false); // Can't expand scalars - IsExpanded() is buggy.
    302 		}
    303 		else if (curType.isArrayType())
    304 			m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, 0));
    305 		else if (curType.isStructType())
    306 			m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, 0));
    307 		else
    308 			DE_ASSERT(false);
    309 	}
    310 }
    311 
    312 template <typename Iterator>
    313 bool isValidTypePath (const VarType& type, Iterator begin, Iterator end)
    314 {
    315 	const VarType*	curType		= &type;
    316 	Iterator		pathIter	= begin;
    317 
    318 	// Process struct member and array element parts of path.
    319 	while (pathIter != end)
    320 	{
    321 		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
    322 		{
    323 			if (!curType->isStructType() || !de::inBounds(pathIter->index, 0, curType->getStructPtr()->getNumMembers()))
    324 				return false;
    325 
    326 			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
    327 		}
    328 		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
    329 		{
    330 			if (!curType->isArrayType() || (curType->getArraySize() != VarType::UNSIZED_ARRAY && !de::inBounds(pathIter->index, 0, curType->getArraySize())))
    331 				return false;
    332 
    333 			curType = &curType->getElementType();
    334 		}
    335 		else
    336 			break;
    337 
    338 		++pathIter;
    339 	}
    340 
    341 	if (pathIter != end)
    342 	{
    343 		DE_ASSERT(pathIter->type == VarTypeComponent::MATRIX_COLUMN || pathIter->type == VarTypeComponent::VECTOR_COMPONENT);
    344 
    345 		// Current type should be basic type.
    346 		if (!curType->isBasicType())
    347 			return false;
    348 
    349 		DataType basicType = curType->getBasicType();
    350 
    351 		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
    352 		{
    353 			if (!isDataTypeMatrix(basicType))
    354 				return false;
    355 
    356 			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
    357 			++pathIter;
    358 		}
    359 
    360 		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
    361 		{
    362 			if (!isDataTypeVector(basicType))
    363 				return false;
    364 
    365 			basicType = getDataTypeScalarType(basicType);
    366 			++pathIter;
    367 		}
    368 	}
    369 
    370 	return pathIter == end;
    371 }
    372 
    373 template <typename Iterator>
    374 VarType getVarType (const VarType& type, Iterator begin, Iterator end)
    375 {
    376 	TCU_CHECK(isValidTypePath(type, begin, end));
    377 
    378 	const VarType*	curType		= &type;
    379 	Iterator		pathIter	= begin;
    380 
    381 	// Process struct member and array element parts of path.
    382 	while (pathIter != end)
    383 	{
    384 		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
    385 			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
    386 		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
    387 			curType = &curType->getElementType();
    388 		else
    389 			break;
    390 
    391 		++pathIter;
    392 	}
    393 
    394 	if (pathIter != end)
    395 	{
    396 		DataType	basicType	= curType->getBasicType();
    397 		Precision	precision	= curType->getPrecision();
    398 
    399 		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
    400 		{
    401 			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
    402 			++pathIter;
    403 		}
    404 
    405 		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
    406 		{
    407 			basicType = getDataTypeScalarType(basicType);
    408 			++pathIter;
    409 		}
    410 
    411 		DE_ASSERT(pathIter == end);
    412 		return VarType(basicType, precision);
    413 	}
    414 	else
    415 		return VarType(*curType);
    416 }
    417 
    418 } // glu
    419 
    420 #endif // _GLUVARTYPEUTIL_HPP
    421