1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "glsltypes_p.h" |
5 | #include "glslsymbols_p.h" |
6 | #include "glslengine_p.h" |
7 | #include "glslparser_p.h" |
8 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | using namespace GLSL; |
12 | |
13 | bool UndefinedType::isEqualTo(const Type *other) const |
14 | { |
15 | if (other && other->asUndefinedType() != nullptr) |
16 | return true; |
17 | return false; |
18 | } |
19 | |
20 | bool UndefinedType::isLessThan(const Type *other) const |
21 | { |
22 | Q_UNUSED(other) |
23 | Q_ASSERT(other != nullptr); |
24 | Q_ASSERT(other->asUndefinedType() != nullptr); |
25 | return false; |
26 | } |
27 | |
28 | bool VoidType::isEqualTo(const Type *other) const |
29 | { |
30 | if (other && other->asVoidType() != nullptr) |
31 | return true; |
32 | return false; |
33 | } |
34 | |
35 | bool VoidType::isLessThan(const Type *other) const |
36 | { |
37 | Q_UNUSED(other) |
38 | Q_ASSERT(other != nullptr); |
39 | Q_ASSERT(other->asVoidType() != nullptr); |
40 | return false; |
41 | } |
42 | |
43 | bool BoolType::isEqualTo(const Type *other) const |
44 | { |
45 | if (other && other->asBoolType() != nullptr) |
46 | return true; |
47 | return false; |
48 | } |
49 | |
50 | bool BoolType::isLessThan(const Type *other) const |
51 | { |
52 | Q_UNUSED(other) |
53 | Q_ASSERT(other != nullptr); |
54 | Q_ASSERT(other->asBoolType() != nullptr); |
55 | return false; |
56 | } |
57 | |
58 | bool IntType::isEqualTo(const Type *other) const |
59 | { |
60 | if (other && other->asIntType() != nullptr) |
61 | return true; |
62 | return false; |
63 | } |
64 | |
65 | bool IntType::isLessThan(const Type *other) const |
66 | { |
67 | Q_UNUSED(other) |
68 | Q_ASSERT(other != nullptr); |
69 | Q_ASSERT(other->asIntType() != nullptr); |
70 | return false; |
71 | } |
72 | |
73 | bool UIntType::isEqualTo(const Type *other) const |
74 | { |
75 | if (other && other->asUIntType() != nullptr) |
76 | return true; |
77 | return false; |
78 | } |
79 | |
80 | bool UIntType::isLessThan(const Type *other) const |
81 | { |
82 | Q_UNUSED(other) |
83 | Q_ASSERT(other != nullptr); |
84 | Q_ASSERT(other->asUIntType() != nullptr); |
85 | return false; |
86 | } |
87 | |
88 | bool FloatType::isEqualTo(const Type *other) const |
89 | { |
90 | if (other && other->asFloatType() != nullptr) |
91 | return true; |
92 | return false; |
93 | } |
94 | |
95 | bool FloatType::isLessThan(const Type *other) const |
96 | { |
97 | Q_UNUSED(other) |
98 | Q_ASSERT(other != nullptr); |
99 | Q_ASSERT(other->asFloatType() != nullptr); |
100 | return false; |
101 | } |
102 | |
103 | bool DoubleType::isEqualTo(const Type *other) const |
104 | { |
105 | if (other && other->asDoubleType() != nullptr) |
106 | return true; |
107 | return false; |
108 | } |
109 | |
110 | bool DoubleType::isLessThan(const Type *other) const |
111 | { |
112 | Q_UNUSED(other) |
113 | Q_ASSERT(other != nullptr); |
114 | Q_ASSERT(other->asDoubleType() != nullptr); |
115 | return false; |
116 | } |
117 | |
118 | QString VectorType::toString() const |
119 | { |
120 | const char *prefix = "" ; |
121 | if (elementType()->asBoolType() != nullptr) |
122 | prefix = "b" ; |
123 | else if (elementType()->asIntType() != nullptr) |
124 | prefix = "i'" ; |
125 | else if (elementType()->asUIntType() != nullptr) |
126 | prefix = "u" ; |
127 | else if (elementType()->asDoubleType() != nullptr) |
128 | prefix = "d" ; |
129 | return QString::fromLatin1(ba: "%1vec%2" ).arg(a: QLatin1String(prefix)).arg(a: _dimension); |
130 | } |
131 | |
132 | void VectorType::add(Symbol *symbol) |
133 | { |
134 | _members.insert(key: symbol->name(), value: symbol); |
135 | } |
136 | |
137 | Symbol *VectorType::find(const QString &name) const |
138 | { |
139 | return _members.value(key: name); |
140 | } |
141 | |
142 | void VectorType::populateMembers(Engine *engine) |
143 | { |
144 | if (_members.isEmpty()) { |
145 | populateMembers(engine, components: "xyzw" ); |
146 | populateMembers(engine, components: "rgba" ); |
147 | populateMembers(engine, components: "stpq" ); |
148 | } |
149 | } |
150 | |
151 | void VectorType::populateMembers(Engine *engine, const char *components) |
152 | { |
153 | // Single component swizzles. |
154 | for (int x = 0; x < _dimension; ++x) { |
155 | const QString *name = engine->identifier(s: components + x, n: 1); |
156 | add(symbol: engine->newVariable(scope: this, name: *name, type: elementType())); |
157 | } |
158 | |
159 | // Two component swizzles. |
160 | const Type *vec2Type; |
161 | if (_dimension == 2) |
162 | vec2Type = this; |
163 | else |
164 | vec2Type = engine->vectorType(elementType: elementType(), dimension: 2); |
165 | for (int x = 0; x < _dimension; ++x) { |
166 | for (int y = 0; y < _dimension; ++y) { |
167 | QString name; |
168 | name += QLatin1Char(components[x]); |
169 | name += QLatin1Char(components[y]); |
170 | add(symbol: engine->newVariable |
171 | (scope: this, name: *engine->identifier(s: name), type: vec2Type)); |
172 | } |
173 | } |
174 | |
175 | // Three component swizzles. |
176 | const Type *vec3Type; |
177 | if (_dimension == 3) |
178 | vec3Type = this; |
179 | else if (_dimension < 3) |
180 | return; |
181 | else |
182 | vec3Type = engine->vectorType(elementType: elementType(), dimension: 3); |
183 | for (int x = 0; x < _dimension; ++x) { |
184 | for (int y = 0; y < _dimension; ++y) { |
185 | for (int z = 0; z < _dimension; ++z) { |
186 | QString name; |
187 | name += QLatin1Char(components[x]); |
188 | name += QLatin1Char(components[y]); |
189 | name += QLatin1Char(components[z]); |
190 | add(symbol: engine->newVariable |
191 | (scope: this, name: *engine->identifier(s: name), type: vec3Type)); |
192 | } |
193 | } |
194 | } |
195 | |
196 | // Four component swizzles. |
197 | if (_dimension != 4) |
198 | return; |
199 | for (int x = 0; x < _dimension; ++x) { |
200 | for (int y = 0; y < _dimension; ++y) { |
201 | for (int z = 0; z < _dimension; ++z) { |
202 | for (int w = 0; w < _dimension; ++w) { |
203 | QString name; |
204 | name += QLatin1Char(components[x]); |
205 | name += QLatin1Char(components[y]); |
206 | name += QLatin1Char(components[z]); |
207 | name += QLatin1Char(components[w]); |
208 | add(symbol: engine->newVariable |
209 | (scope: this, name: *engine->identifier(s: name), type: this)); |
210 | } |
211 | } |
212 | } |
213 | } |
214 | } |
215 | |
216 | bool VectorType::isEqualTo(const Type *other) const |
217 | { |
218 | if (other) { |
219 | if (const VectorType *v = other->asVectorType()) { |
220 | if (_dimension != v->dimension()) |
221 | return false; |
222 | else if (elementType() != v->elementType()) |
223 | return false; |
224 | return true; |
225 | } |
226 | } |
227 | return false; |
228 | } |
229 | |
230 | bool VectorType::isLessThan(const Type *other) const |
231 | { |
232 | Q_ASSERT(other != nullptr); |
233 | const VectorType *vec = other->asVectorType(); |
234 | Q_ASSERT(vec != nullptr); |
235 | if (_dimension < vec->dimension()) |
236 | return true; |
237 | else if (_dimension == vec->dimension() && elementType() < vec->elementType()) |
238 | return true; |
239 | return false; |
240 | } |
241 | |
242 | QString MatrixType::toString() const |
243 | { |
244 | const char *prefix = "" ; |
245 | if (elementType()->asBoolType() != nullptr) |
246 | prefix = "b" ; |
247 | else if (elementType()->asIntType() != nullptr) |
248 | prefix = "i" ; |
249 | else if (elementType()->asUIntType() != nullptr) |
250 | prefix = "u" ; |
251 | else if (elementType()->asDoubleType() != nullptr) |
252 | prefix = "d" ; |
253 | return QString::fromLatin1(ba: "%1mat%2x%3" ).arg(a: QLatin1String(prefix)).arg(a: _columns).arg(a: _rows); |
254 | } |
255 | |
256 | bool MatrixType::isEqualTo(const Type *other) const |
257 | { |
258 | if (other) { |
259 | if (const MatrixType *v = other->asMatrixType()) { |
260 | if (_columns != v->columns()) |
261 | return false; |
262 | else if (_rows != v->rows()) |
263 | return false; |
264 | else if (_elementType != v->elementType()) |
265 | return false; |
266 | return true; |
267 | } |
268 | } |
269 | return false; |
270 | } |
271 | |
272 | bool MatrixType::isLessThan(const Type *other) const |
273 | { |
274 | Q_ASSERT(other != nullptr); |
275 | const MatrixType *mat = other->asMatrixType(); |
276 | Q_ASSERT(mat != nullptr); |
277 | if (_columns < mat->columns()) { |
278 | return true; |
279 | } else if (_columns == mat->columns()) { |
280 | if (_rows < mat->rows()) |
281 | return true; |
282 | else if (_rows == mat->rows() && _elementType < mat->elementType()) |
283 | return true; |
284 | } |
285 | return false; |
286 | } |
287 | |
288 | QString ArrayType::toString() const |
289 | { |
290 | return elementType()->toString() + QLatin1String("[]" ); |
291 | } |
292 | |
293 | bool ArrayType::isEqualTo(const Type *other) const |
294 | { |
295 | if (other) { |
296 | if (const ArrayType *array = other->asArrayType()) |
297 | return elementType()->isEqualTo(other: array->elementType()); |
298 | } |
299 | return false; |
300 | } |
301 | |
302 | bool ArrayType::isLessThan(const Type *other) const |
303 | { |
304 | Q_ASSERT(other != nullptr); |
305 | const ArrayType *array = other->asArrayType(); |
306 | Q_ASSERT(array != nullptr); |
307 | return elementType() < array->elementType(); |
308 | } |
309 | |
310 | QList<Symbol *> Struct::members() const |
311 | { |
312 | QList<Symbol *> m; |
313 | foreach (Symbol *s, _members) { |
314 | if (! s->name().isEmpty()) |
315 | m.append(t: s); |
316 | } |
317 | return m; |
318 | } |
319 | |
320 | void Struct::add(Symbol *member) |
321 | { |
322 | _members.append(t: member); |
323 | } |
324 | |
325 | Symbol *Struct::find(const QString &name) const |
326 | { |
327 | foreach (Symbol *s, _members) { |
328 | if (s->name() == name) |
329 | return s; |
330 | } |
331 | return nullptr; |
332 | } |
333 | |
334 | bool Struct::isEqualTo(const Type *other) const |
335 | { |
336 | Q_UNUSED(other) |
337 | return false; |
338 | } |
339 | |
340 | bool Struct::isLessThan(const Type *other) const |
341 | { |
342 | Q_UNUSED(other) |
343 | return false; |
344 | } |
345 | |
346 | |
347 | QString Function::toString() const |
348 | { |
349 | return prettyPrint(); |
350 | } |
351 | |
352 | QString Function::prettyPrint() const |
353 | { |
354 | QString proto; |
355 | proto += _returnType->toString(); |
356 | proto += QLatin1Char(' '); |
357 | proto += name(); |
358 | proto += QLatin1Char('('); |
359 | for (int i = 0; i < _arguments.size(); ++i) { |
360 | if (i != 0) |
361 | proto += QLatin1String(", " ); |
362 | Argument *arg = _arguments.at(i); |
363 | proto += arg->type()->toString(); |
364 | proto += QLatin1Char(' '); |
365 | proto += arg->name(); |
366 | } |
367 | proto += QLatin1Char(')'); |
368 | return proto; |
369 | } |
370 | |
371 | const Type *Function::returnType() const |
372 | { |
373 | return _returnType; |
374 | } |
375 | |
376 | void Function::setReturnType(const Type *returnType) |
377 | { |
378 | _returnType = returnType; |
379 | } |
380 | |
381 | QVector<Argument *> Function::arguments() const |
382 | { |
383 | return _arguments; |
384 | } |
385 | |
386 | void Function::addArgument(Argument *arg) |
387 | { |
388 | _arguments.append(t: arg); |
389 | } |
390 | |
391 | int Function::argumentCount() const |
392 | { |
393 | return _arguments.size(); |
394 | } |
395 | |
396 | Argument *Function::argumentAt(int index) const |
397 | { |
398 | return _arguments.at(i: index); |
399 | } |
400 | |
401 | bool Function::isEqualTo(const Type *other) const |
402 | { |
403 | Q_UNUSED(other) |
404 | return false; |
405 | } |
406 | |
407 | bool Function::isLessThan(const Type *other) const |
408 | { |
409 | Q_UNUSED(other) |
410 | return false; |
411 | } |
412 | |
413 | QList<Symbol *> Function::members() const |
414 | { |
415 | QList<Symbol *> m; |
416 | foreach (Argument *arg, _arguments) { |
417 | if (! arg->name().isEmpty()) |
418 | m.append(t: arg); |
419 | } |
420 | return m; |
421 | } |
422 | |
423 | Symbol *Function::find(const QString &name) const |
424 | { |
425 | foreach (Argument *arg, _arguments) { |
426 | if (arg->name() == name) |
427 | return arg; |
428 | } |
429 | return nullptr; |
430 | } |
431 | |
432 | QString SamplerType::toString() const |
433 | { |
434 | return QLatin1String(Parser::spell[_kind]); |
435 | } |
436 | |
437 | bool SamplerType::isEqualTo(const Type *other) const |
438 | { |
439 | if (other) { |
440 | if (const SamplerType *samp = other->asSamplerType()) |
441 | return _kind == samp->kind(); |
442 | } |
443 | return false; |
444 | } |
445 | |
446 | bool SamplerType::isLessThan(const Type *other) const |
447 | { |
448 | Q_ASSERT(other != nullptr); |
449 | const SamplerType *samp = other->asSamplerType(); |
450 | Q_ASSERT(samp != nullptr); |
451 | return _kind < samp->kind(); |
452 | } |
453 | |
454 | OverloadSet::OverloadSet(Scope *enclosingScope) |
455 | : Scope(enclosingScope) |
456 | { |
457 | } |
458 | |
459 | QVector<Function *> OverloadSet::functions() const |
460 | { |
461 | return _functions; |
462 | } |
463 | |
464 | void OverloadSet::addFunction(Function *function) |
465 | { |
466 | _functions.append(t: function); |
467 | } |
468 | |
469 | const Type *OverloadSet::type() const |
470 | { |
471 | return this; |
472 | } |
473 | |
474 | Symbol *OverloadSet::find(const QString &) const |
475 | { |
476 | return nullptr; |
477 | } |
478 | |
479 | void OverloadSet::add(Symbol *symbol) |
480 | { |
481 | if (symbol) { |
482 | if (Function *fun = symbol->asFunction()) |
483 | addFunction(function: fun); |
484 | } |
485 | } |
486 | |
487 | bool OverloadSet::isEqualTo(const Type *other) const |
488 | { |
489 | Q_UNUSED(other) |
490 | return false; |
491 | } |
492 | |
493 | bool OverloadSet::isLessThan(const Type *other) const |
494 | { |
495 | Q_UNUSED(other) |
496 | return false; |
497 | } |
498 | |
499 | QT_END_NAMESPACE |
500 | |