Vulkan: Add wide-color tests
[platform/upstream/VK-GL-CTS.git] / framework / opengl / gluVarTypeUtil.hpp
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