Merge vk-gl-cts/vulkan-cts-1.0.1 into vk-gl-cts/vulkan-cts-1.0.2
[platform/upstream/VK-GL-CTS.git] / framework / opengl / gluVarTypeUtil.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES Utilities
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 Shader variable type utilities.
22  *//*--------------------------------------------------------------------*/
23
24 #include "gluVarTypeUtil.hpp"
25
26 #include <stdlib.h>
27
28 namespace glu
29 {
30
31 // VarTokenizer
32
33 VarTokenizer::VarTokenizer (const char* str)
34         : m_str                 (str)
35         , m_token               (TOKEN_LAST)
36         , m_tokenStart  (0)
37         , m_tokenLen    (0)
38 {
39         advance();
40 }
41
42 int VarTokenizer::getNumber (void) const
43 {
44         return atoi(getIdentifier().c_str());
45 }
46
47 static inline bool      isNum                           (char c) { return de::inRange(c, '0', '9'); }
48 static inline bool      isAlpha                         (char c) { return de::inRange(c, 'a', 'z') || de::inRange(c, 'A', 'Z'); }
49 static inline bool      isIdentifierChar        (char c) { return isAlpha(c) || isNum(c) || c == '_'; }
50
51 void VarTokenizer::advance (void)
52 {
53         DE_ASSERT(m_token != TOKEN_END);
54
55         m_tokenStart    += m_tokenLen;
56         m_token                  = TOKEN_LAST;
57         m_tokenLen               = 1;
58
59         if (m_str[m_tokenStart] == '[')
60                 m_token = TOKEN_LEFT_BRACKET;
61         else if (m_str[m_tokenStart] == ']')
62                 m_token = TOKEN_RIGHT_BRACKET;
63         else if (m_str[m_tokenStart] == 0)
64                 m_token = TOKEN_END;
65         else if (m_str[m_tokenStart] == '.')
66                 m_token = TOKEN_PERIOD;
67         else if (isNum(m_str[m_tokenStart]))
68         {
69                 m_token = TOKEN_NUMBER;
70                 while (isNum(m_str[m_tokenStart+m_tokenLen]))
71                         m_tokenLen += 1;
72         }
73         else if (isIdentifierChar(m_str[m_tokenStart]))
74         {
75                 m_token = TOKEN_IDENTIFIER;
76                 while (isIdentifierChar(m_str[m_tokenStart+m_tokenLen]))
77                         m_tokenLen += 1;
78         }
79         else
80                 TCU_FAIL("Unexpected character");
81 }
82
83 // SubTypeAccess
84
85 SubTypeAccess::SubTypeAccess (const VarType& type)
86         : m_type(type)
87 {
88 }
89
90 std::string parseVariableName (const char* nameWithPath)
91 {
92         VarTokenizer tokenizer(nameWithPath);
93         TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
94         return tokenizer.getIdentifier();
95 }
96
97 void parseTypePath (const char* nameWithPath, const VarType& type, TypeComponentVector& path)
98 {
99         VarTokenizer tokenizer(nameWithPath);
100
101         if (tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER)
102                 tokenizer.advance();
103
104         path.clear();
105         while (tokenizer.getToken() != VarTokenizer::TOKEN_END)
106         {
107                 VarType curType = getVarType(type, path);
108
109                 if (tokenizer.getToken() == VarTokenizer::TOKEN_PERIOD)
110                 {
111                         tokenizer.advance();
112                         TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_IDENTIFIER);
113                         TCU_CHECK_MSG(curType.isStructType(), "Invalid field selector");
114
115                         // Find member.
116                         std::string             memberName      = tokenizer.getIdentifier();
117                         int                             ndx                     = 0;
118                         for (; ndx < curType.getStructPtr()->getNumMembers(); ndx++)
119                         {
120                                 if (memberName == curType.getStructPtr()->getMember(ndx).getName())
121                                         break;
122                         }
123                         TCU_CHECK_MSG(ndx < curType.getStructPtr()->getNumMembers(), "Member not found in type");
124
125                         path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, ndx));
126                         tokenizer.advance();
127                 }
128                 else if (tokenizer.getToken() == VarTokenizer::TOKEN_LEFT_BRACKET)
129                 {
130                         tokenizer.advance();
131                         TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_NUMBER);
132
133                         int ndx = tokenizer.getNumber();
134
135                         if (curType.isArrayType())
136                         {
137                                 TCU_CHECK(de::inBounds(ndx, 0, curType.getArraySize()));
138                                 path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, ndx));
139                         }
140                         else if (curType.isBasicType() && isDataTypeMatrix(curType.getBasicType()))
141                         {
142                                 TCU_CHECK(de::inBounds(ndx, 0, getDataTypeMatrixNumColumns(curType.getBasicType())));
143                                 path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, ndx));
144                         }
145                         else if (curType.isBasicType() && isDataTypeVector(curType.getBasicType()))
146                         {
147                                 TCU_CHECK(de::inBounds(ndx, 0, getDataTypeScalarSize(curType.getBasicType())));
148                                 path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, ndx));
149                         }
150                         else
151                                 TCU_FAIL("Invalid subscript");
152
153                         tokenizer.advance();
154                         TCU_CHECK(tokenizer.getToken() == VarTokenizer::TOKEN_RIGHT_BRACKET);
155                         tokenizer.advance();
156                 }
157                 else
158                         TCU_FAIL("Unexpected token");
159         }
160 }
161
162 std::ostream& operator<< (std::ostream& str, const TypeAccessFormat& format)
163 {
164         const VarType* curType = &format.type;
165
166         for (TypeComponentVector::const_iterator iter = format.path.begin(); iter != format.path.end(); iter++)
167         {
168                 switch (iter->type)
169                 {
170                         case VarTypeComponent::ARRAY_ELEMENT:
171                                 curType = &curType->getElementType(); // Update current type.
172                                 // Fall-through.
173
174                         case VarTypeComponent::MATRIX_COLUMN:
175                         case VarTypeComponent::VECTOR_COMPONENT:
176                                 str << "[" << iter->index << "]";
177                                 break;
178
179                         case VarTypeComponent::STRUCT_MEMBER:
180                         {
181                                 const StructMember& member = curType->getStructPtr()->getMember(iter->index);
182                                 str << "." << member.getName();
183                                 curType = &member.getType();
184                                 break;
185                         }
186
187                         default:
188                                 DE_ASSERT(false);
189                 }
190         }
191
192         return str;
193 }
194
195 } // glu