1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Random Shader Generator
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 Variable Type class.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "rsgVariableType.hpp"
25 #include "rsgToken.hpp"
26 
27 using std::vector;
28 
29 namespace rsg
30 {
31 
operator =(const VariableType & other)32 VariableType& VariableType::operator= (const VariableType& other)
33 {
34 	if (this == &other)
35 		return *this;
36 
37 	delete m_elementType;
38 
39 	m_elementType	= DE_NULL;
40 	m_baseType		= other.m_baseType;
41 	m_precision		= other.m_precision;
42 	m_typeName		= other.m_typeName;
43 	m_numElements	= other.m_numElements;
44 	m_members		= other.m_members;
45 	m_elementType	= DE_NULL;
46 
47 	if (other.m_elementType)
48 		m_elementType = new VariableType(*other.m_elementType);
49 
50 	return *this;
51 }
52 
VariableType(const VariableType & other)53 VariableType::VariableType (const VariableType& other)
54 	: m_elementType(DE_NULL)
55 {
56 	*this = other;
57 }
58 
operator !=(const VariableType & other) const59 bool VariableType::operator!= (const VariableType& other) const
60 {
61 	if (m_baseType != other.m_baseType)
62 		return true;
63 	if (m_precision != other.m_precision)
64 		return true;
65 	if (m_numElements != other.m_numElements)
66 		return true;
67 	if (!!m_elementType != !!other.m_elementType)
68 		return true;
69 	if (m_elementType && *m_elementType != *other.m_elementType)
70 		return true;
71 	if (m_members != other.m_members)
72 		return true;
73 	return false;
74 }
75 
operator ==(const VariableType & other) const76 bool VariableType::operator== (const VariableType& other) const
77 {
78 	return !(*this != other);
79 }
80 
getScalarSize(void) const81 int VariableType::getScalarSize (void) const
82 {
83 	switch (m_baseType)
84 	{
85 		case TYPE_VOID:
86 		case TYPE_FLOAT:
87 		case TYPE_INT:
88 		case TYPE_BOOL:
89 		case TYPE_SAMPLER_2D:
90 		case TYPE_SAMPLER_CUBE:
91 			return m_numElements;
92 
93 		case TYPE_STRUCT:
94 		{
95 			int sum = 0;
96 			for (vector<Member>::const_iterator i = m_members.begin(); i != m_members.end(); i++)
97 				sum += i->getType().getScalarSize();
98 			return sum;
99 		}
100 
101 		case TYPE_ARRAY:
102 		{
103 			DE_ASSERT(m_elementType);
104 			return m_elementType->getScalarSize() * m_numElements;
105 		}
106 
107 		default:
108 			DE_ASSERT(false);
109 			return 0;
110 	}
111 }
112 
getMemberScalarOffset(int memberNdx) const113 int VariableType::getMemberScalarOffset (int memberNdx) const
114 {
115 	DE_ASSERT(isStruct());
116 
117 	int curOffset = 0;
118 	for (vector<Member>::const_iterator i = m_members.begin(); i != m_members.begin() + memberNdx; i++)
119 		curOffset += i->getType().getScalarSize();
120 
121 	return curOffset;
122 }
123 
getElementScalarOffset(int elementNdx) const124 int VariableType::getElementScalarOffset (int elementNdx) const
125 {
126 	DE_ASSERT(isArray());
127 	return elementNdx * getElementType().getScalarSize();
128 }
129 
getScalarType(Type baseType)130 const VariableType& VariableType::getScalarType (Type baseType)
131 {
132 	switch (baseType)
133 	{
134 		case TYPE_FLOAT:
135 		{
136 			static const VariableType s_floatTypes[] =
137 			{
138 				VariableType(TYPE_FLOAT, 1)
139 				// \todo [pyry] Extend with different precision variants?
140 			};
141 			return s_floatTypes[0];
142 		}
143 
144 		case TYPE_INT:
145 		{
146 			static const VariableType s_intTypes[] =
147 			{
148 				VariableType(TYPE_INT, 1)
149 			};
150 			return s_intTypes[0];
151 		}
152 
153 		case TYPE_BOOL:
154 		{
155 			static const VariableType s_boolTypes[] =
156 			{
157 				VariableType(TYPE_BOOL, 1)
158 			};
159 			return s_boolTypes[0];
160 		}
161 
162 		case TYPE_SAMPLER_2D:
163 		{
164 			static const VariableType sampler2DType = VariableType(TYPE_SAMPLER_2D, 1);
165 			return sampler2DType;
166 		}
167 
168 		case TYPE_SAMPLER_CUBE:
169 		{
170 			static const VariableType samplerCubeType = VariableType(TYPE_SAMPLER_CUBE, 1);
171 			return samplerCubeType;
172 		}
173 
174 		default:
175 			DE_ASSERT(DE_FALSE);
176 			throw Exception("VariableType::getScalarType(): unsupported type");
177 	}
178 }
179 
getElementType(void) const180 const VariableType& VariableType::getElementType (void) const
181 {
182 	DE_ASSERT(m_precision == PRECISION_NONE); // \todo [pyry] Precision
183 	switch (m_baseType)
184 	{
185 		case TYPE_FLOAT:
186 		case TYPE_INT:
187 		case TYPE_BOOL:
188 		case TYPE_SAMPLER_2D:
189 		case TYPE_SAMPLER_CUBE:
190 			return getScalarType(m_baseType);
191 
192 		case TYPE_ARRAY:
193 		{
194 			DE_ASSERT(m_elementType);
195 			return *m_elementType;
196 		}
197 
198 		default:
199 			DE_ASSERT(DE_FALSE);
200 			throw Exception("VariableType::getElementType(): unsupported type");
201 	}
202 }
203 
tokenizeShortType(TokenStream & str) const204 void VariableType::tokenizeShortType (TokenStream& str) const
205 {
206 	switch (m_precision)
207 	{
208 		case PRECISION_LOW:		str << Token::LOW_PRECISION;	break;
209 		case PRECISION_MEDIUM:	str << Token::MEDIUM_PRECISION;	break;
210 		case PRECISION_HIGH:	str << Token::HIGH_PRECISION;	break;
211 		default:				/* nothing */					break;
212 	}
213 
214 	switch (m_baseType)
215 	{
216 		case TYPE_VOID:
217 			str << Token::VOID;
218 			break;
219 
220 		case TYPE_FLOAT:
221 			switch (m_numElements)
222 			{
223 				case 1:		str << Token::FLOAT;		break;
224 				case 2:		str << Token::VEC2;			break;
225 				case 3:		str << Token::VEC3;			break;
226 				case 4:		str << Token::VEC4;			break;
227 				default:	DE_ASSERT(DE_FALSE);		break;
228 			}
229 			break;
230 
231 		case TYPE_INT:
232 			switch (m_numElements)
233 			{
234 				case 1:		str << Token::INT;			break;
235 				case 2:		str << Token::IVEC2;		break;
236 				case 3:		str << Token::IVEC3;		break;
237 				case 4:		str << Token::IVEC4;		break;
238 				default:	DE_ASSERT(DE_FALSE);		break;
239 			}
240 			break;
241 
242 		case TYPE_BOOL:
243 			switch (m_numElements)
244 			{
245 				case 1:		str << Token::BOOL;			break;
246 				case 2:		str << Token::BVEC2;		break;
247 				case 3:		str << Token::BVEC3;		break;
248 				case 4:		str << Token::BVEC4;		break;
249 				default:	DE_ASSERT(DE_FALSE);		break;
250 			}
251 			break;
252 
253 		case TYPE_SAMPLER_2D:		str << Token::SAMPLER2D;	break;
254 		case TYPE_SAMPLER_CUBE:		str << Token::SAMPLERCUBE;	break;
255 
256 		case TYPE_STRUCT:
257 			DE_ASSERT(m_typeName != "");
258 			str << Token(m_typeName.c_str());
259 			break;
260 
261 		case TYPE_ARRAY:
262 			DE_ASSERT(m_elementType);
263 			m_elementType->tokenizeShortType(str);
264 			str << Token::LEFT_BRACKET << Token(m_numElements) << Token::RIGHT_BRACKET;
265 			break;
266 
267 		default:
268 			DE_ASSERT(DE_FALSE);
269 			break;
270 	}
271 }
272 
273 } // rsg
274