1//
2// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// utilities.cpp: Conversion functions and other utility routines.
8
9#include "common/utilities.h"
10#include <GLSLANG/ShaderVars.h>
11#include "common/mathutil.h"
12#include "common/platform.h"
13
14#include <set>
15
16#if defined(ANGLE_ENABLE_WINDOWS_STORE)
17# include <windows.applicationmodel.core.h>
18# include <windows.graphics.display.h>
19# include <wrl.h>
20# include <wrl/wrappers/corewrappers.h>
21#endif
22
23namespace
24{
25
26template <class IndexType>
27gl::IndexRange ComputeTypedIndexRange(const IndexType *indices,
28 size_t count,
29 bool primitiveRestartEnabled,
30 GLuint primitiveRestartIndex)
31{
32 ASSERT(count > 0);
33
34 IndexType minIndex = 0;
35 IndexType maxIndex = 0;
36 size_t nonPrimitiveRestartIndices = 0;
37
38 if (primitiveRestartEnabled)
39 {
40 // Find the first non-primitive restart index to initialize the min and max values
41 size_t i = 0;
42 for (; i < count; i++)
43 {
44 if (indices[i] != primitiveRestartIndex)
45 {
46 minIndex = indices[i];
47 maxIndex = indices[i];
48 nonPrimitiveRestartIndices++;
49 break;
50 }
51 }
52
53 // Loop over the rest of the indices
54 for (; i < count; i++)
55 {
56 if (indices[i] != primitiveRestartIndex)
57 {
58 if (minIndex > indices[i])
59 {
60 minIndex = indices[i];
61 }
62 if (maxIndex < indices[i])
63 {
64 maxIndex = indices[i];
65 }
66 nonPrimitiveRestartIndices++;
67 }
68 }
69 }
70 else
71 {
72 minIndex = indices[0];
73 maxIndex = indices[0];
74 nonPrimitiveRestartIndices = count;
75
76 for (size_t i = 1; i < count; i++)
77 {
78 if (minIndex > indices[i])
79 {
80 minIndex = indices[i];
81 }
82 if (maxIndex < indices[i])
83 {
84 maxIndex = indices[i];
85 }
86 }
87 }
88
89 return gl::IndexRange(static_cast<size_t>(minIndex), static_cast<size_t>(maxIndex),
90 nonPrimitiveRestartIndices);
91}
92
93} // anonymous namespace
94
95namespace gl
96{
97
98int VariableComponentCount(GLenum type)
99{
100 return VariableRowCount(type) * VariableColumnCount(type);
101}
102
103GLenum VariableComponentType(GLenum type)
104{
105 switch (type)
106 {
107 case GL_BOOL:
108 case GL_BOOL_VEC2:
109 case GL_BOOL_VEC3:
110 case GL_BOOL_VEC4:
111 return GL_BOOL;
112 case GL_FLOAT:
113 case GL_FLOAT_VEC2:
114 case GL_FLOAT_VEC3:
115 case GL_FLOAT_VEC4:
116 case GL_FLOAT_MAT2:
117 case GL_FLOAT_MAT3:
118 case GL_FLOAT_MAT4:
119 case GL_FLOAT_MAT2x3:
120 case GL_FLOAT_MAT3x2:
121 case GL_FLOAT_MAT2x4:
122 case GL_FLOAT_MAT4x2:
123 case GL_FLOAT_MAT3x4:
124 case GL_FLOAT_MAT4x3:
125 return GL_FLOAT;
126 case GL_INT:
127 case GL_SAMPLER_2D:
128 case GL_SAMPLER_2D_RECT_ANGLE:
129 case GL_SAMPLER_3D:
130 case GL_SAMPLER_CUBE:
131 case GL_SAMPLER_2D_ARRAY:
132 case GL_SAMPLER_EXTERNAL_OES:
133 case GL_SAMPLER_2D_MULTISAMPLE:
134 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
135 case GL_INT_SAMPLER_2D:
136 case GL_INT_SAMPLER_3D:
137 case GL_INT_SAMPLER_CUBE:
138 case GL_INT_SAMPLER_2D_ARRAY:
139 case GL_INT_SAMPLER_2D_MULTISAMPLE:
140 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
141 case GL_UNSIGNED_INT_SAMPLER_2D:
142 case GL_UNSIGNED_INT_SAMPLER_3D:
143 case GL_UNSIGNED_INT_SAMPLER_CUBE:
144 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
145 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
146 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
147 case GL_SAMPLER_2D_SHADOW:
148 case GL_SAMPLER_CUBE_SHADOW:
149 case GL_SAMPLER_2D_ARRAY_SHADOW:
150 case GL_INT_VEC2:
151 case GL_INT_VEC3:
152 case GL_INT_VEC4:
153 case GL_IMAGE_2D:
154 case GL_INT_IMAGE_2D:
155 case GL_UNSIGNED_INT_IMAGE_2D:
156 case GL_IMAGE_3D:
157 case GL_INT_IMAGE_3D:
158 case GL_UNSIGNED_INT_IMAGE_3D:
159 case GL_IMAGE_2D_ARRAY:
160 case GL_INT_IMAGE_2D_ARRAY:
161 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
162 case GL_IMAGE_CUBE:
163 case GL_INT_IMAGE_CUBE:
164 case GL_UNSIGNED_INT_IMAGE_CUBE:
165 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
166 return GL_INT;
167 case GL_UNSIGNED_INT:
168 case GL_UNSIGNED_INT_VEC2:
169 case GL_UNSIGNED_INT_VEC3:
170 case GL_UNSIGNED_INT_VEC4:
171 return GL_UNSIGNED_INT;
172 default:
173 UNREACHABLE();
174 }
175
176 return GL_NONE;
177}
178
179size_t VariableComponentSize(GLenum type)
180{
181 switch (type)
182 {
183 case GL_BOOL:
184 return sizeof(GLint);
185 case GL_FLOAT:
186 return sizeof(GLfloat);
187 case GL_INT:
188 return sizeof(GLint);
189 case GL_UNSIGNED_INT:
190 return sizeof(GLuint);
191 default:
192 UNREACHABLE();
193 }
194
195 return 0;
196}
197
198size_t VariableInternalSize(GLenum type)
199{
200 // Expanded to 4-element vectors
201 return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4;
202}
203
204size_t VariableExternalSize(GLenum type)
205{
206 return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type);
207}
208
209GLenum VariableBoolVectorType(GLenum type)
210{
211 switch (type)
212 {
213 case GL_FLOAT:
214 case GL_INT:
215 case GL_UNSIGNED_INT:
216 return GL_BOOL;
217 case GL_FLOAT_VEC2:
218 case GL_INT_VEC2:
219 case GL_UNSIGNED_INT_VEC2:
220 return GL_BOOL_VEC2;
221 case GL_FLOAT_VEC3:
222 case GL_INT_VEC3:
223 case GL_UNSIGNED_INT_VEC3:
224 return GL_BOOL_VEC3;
225 case GL_FLOAT_VEC4:
226 case GL_INT_VEC4:
227 case GL_UNSIGNED_INT_VEC4:
228 return GL_BOOL_VEC4;
229
230 default:
231 UNREACHABLE();
232 return GL_NONE;
233 }
234}
235
236int VariableRowCount(GLenum type)
237{
238 switch (type)
239 {
240 case GL_NONE:
241 return 0;
242 case GL_BOOL:
243 case GL_FLOAT:
244 case GL_INT:
245 case GL_UNSIGNED_INT:
246 case GL_BOOL_VEC2:
247 case GL_FLOAT_VEC2:
248 case GL_INT_VEC2:
249 case GL_UNSIGNED_INT_VEC2:
250 case GL_BOOL_VEC3:
251 case GL_FLOAT_VEC3:
252 case GL_INT_VEC3:
253 case GL_UNSIGNED_INT_VEC3:
254 case GL_BOOL_VEC4:
255 case GL_FLOAT_VEC4:
256 case GL_INT_VEC4:
257 case GL_UNSIGNED_INT_VEC4:
258 case GL_SAMPLER_2D:
259 case GL_SAMPLER_3D:
260 case GL_SAMPLER_CUBE:
261 case GL_SAMPLER_2D_ARRAY:
262 case GL_SAMPLER_EXTERNAL_OES:
263 case GL_SAMPLER_2D_RECT_ANGLE:
264 case GL_SAMPLER_2D_MULTISAMPLE:
265 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
266 case GL_INT_SAMPLER_2D:
267 case GL_INT_SAMPLER_3D:
268 case GL_INT_SAMPLER_CUBE:
269 case GL_INT_SAMPLER_2D_ARRAY:
270 case GL_INT_SAMPLER_2D_MULTISAMPLE:
271 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
272 case GL_UNSIGNED_INT_SAMPLER_2D:
273 case GL_UNSIGNED_INT_SAMPLER_3D:
274 case GL_UNSIGNED_INT_SAMPLER_CUBE:
275 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
276 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
277 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
278 case GL_SAMPLER_2D_SHADOW:
279 case GL_SAMPLER_CUBE_SHADOW:
280 case GL_SAMPLER_2D_ARRAY_SHADOW:
281 case GL_IMAGE_2D:
282 case GL_INT_IMAGE_2D:
283 case GL_UNSIGNED_INT_IMAGE_2D:
284 case GL_IMAGE_2D_ARRAY:
285 case GL_INT_IMAGE_2D_ARRAY:
286 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
287 case GL_IMAGE_3D:
288 case GL_INT_IMAGE_3D:
289 case GL_UNSIGNED_INT_IMAGE_3D:
290 case GL_IMAGE_CUBE:
291 case GL_INT_IMAGE_CUBE:
292 case GL_UNSIGNED_INT_IMAGE_CUBE:
293 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
294 return 1;
295 case GL_FLOAT_MAT2:
296 case GL_FLOAT_MAT3x2:
297 case GL_FLOAT_MAT4x2:
298 return 2;
299 case GL_FLOAT_MAT3:
300 case GL_FLOAT_MAT2x3:
301 case GL_FLOAT_MAT4x3:
302 return 3;
303 case GL_FLOAT_MAT4:
304 case GL_FLOAT_MAT2x4:
305 case GL_FLOAT_MAT3x4:
306 return 4;
307 default:
308 UNREACHABLE();
309 }
310
311 return 0;
312}
313
314int VariableColumnCount(GLenum type)
315{
316 switch (type)
317 {
318 case GL_NONE:
319 return 0;
320 case GL_BOOL:
321 case GL_FLOAT:
322 case GL_INT:
323 case GL_UNSIGNED_INT:
324 case GL_SAMPLER_2D:
325 case GL_SAMPLER_3D:
326 case GL_SAMPLER_CUBE:
327 case GL_SAMPLER_2D_ARRAY:
328 case GL_SAMPLER_2D_MULTISAMPLE:
329 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
330 case GL_INT_SAMPLER_2D:
331 case GL_INT_SAMPLER_3D:
332 case GL_INT_SAMPLER_CUBE:
333 case GL_INT_SAMPLER_2D_ARRAY:
334 case GL_INT_SAMPLER_2D_MULTISAMPLE:
335 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
336 case GL_SAMPLER_EXTERNAL_OES:
337 case GL_SAMPLER_2D_RECT_ANGLE:
338 case GL_UNSIGNED_INT_SAMPLER_2D:
339 case GL_UNSIGNED_INT_SAMPLER_3D:
340 case GL_UNSIGNED_INT_SAMPLER_CUBE:
341 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
342 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
343 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
344 case GL_SAMPLER_2D_SHADOW:
345 case GL_SAMPLER_CUBE_SHADOW:
346 case GL_SAMPLER_2D_ARRAY_SHADOW:
347 case GL_IMAGE_2D:
348 case GL_INT_IMAGE_2D:
349 case GL_UNSIGNED_INT_IMAGE_2D:
350 case GL_IMAGE_3D:
351 case GL_INT_IMAGE_3D:
352 case GL_UNSIGNED_INT_IMAGE_3D:
353 case GL_IMAGE_2D_ARRAY:
354 case GL_INT_IMAGE_2D_ARRAY:
355 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
356 case GL_IMAGE_CUBE:
357 case GL_INT_IMAGE_CUBE:
358 case GL_UNSIGNED_INT_IMAGE_CUBE:
359 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
360 return 1;
361 case GL_BOOL_VEC2:
362 case GL_FLOAT_VEC2:
363 case GL_INT_VEC2:
364 case GL_UNSIGNED_INT_VEC2:
365 case GL_FLOAT_MAT2:
366 case GL_FLOAT_MAT2x3:
367 case GL_FLOAT_MAT2x4:
368 return 2;
369 case GL_BOOL_VEC3:
370 case GL_FLOAT_VEC3:
371 case GL_INT_VEC3:
372 case GL_UNSIGNED_INT_VEC3:
373 case GL_FLOAT_MAT3:
374 case GL_FLOAT_MAT3x2:
375 case GL_FLOAT_MAT3x4:
376 return 3;
377 case GL_BOOL_VEC4:
378 case GL_FLOAT_VEC4:
379 case GL_INT_VEC4:
380 case GL_UNSIGNED_INT_VEC4:
381 case GL_FLOAT_MAT4:
382 case GL_FLOAT_MAT4x2:
383 case GL_FLOAT_MAT4x3:
384 return 4;
385 default:
386 UNREACHABLE();
387 }
388
389 return 0;
390}
391
392bool IsSamplerType(GLenum type)
393{
394 switch (type)
395 {
396 case GL_SAMPLER_2D:
397 case GL_SAMPLER_3D:
398 case GL_SAMPLER_CUBE:
399 case GL_SAMPLER_2D_ARRAY:
400 case GL_SAMPLER_EXTERNAL_OES:
401 case GL_SAMPLER_2D_MULTISAMPLE:
402 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
403 case GL_SAMPLER_2D_RECT_ANGLE:
404 case GL_INT_SAMPLER_2D:
405 case GL_INT_SAMPLER_3D:
406 case GL_INT_SAMPLER_CUBE:
407 case GL_INT_SAMPLER_2D_ARRAY:
408 case GL_INT_SAMPLER_2D_MULTISAMPLE:
409 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
410 case GL_UNSIGNED_INT_SAMPLER_2D:
411 case GL_UNSIGNED_INT_SAMPLER_3D:
412 case GL_UNSIGNED_INT_SAMPLER_CUBE:
413 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
414 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
415 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
416 case GL_SAMPLER_2D_SHADOW:
417 case GL_SAMPLER_CUBE_SHADOW:
418 case GL_SAMPLER_2D_ARRAY_SHADOW:
419 return true;
420 }
421
422 return false;
423}
424
425bool IsImageType(GLenum type)
426{
427 switch (type)
428 {
429 case GL_IMAGE_2D:
430 case GL_INT_IMAGE_2D:
431 case GL_UNSIGNED_INT_IMAGE_2D:
432 case GL_IMAGE_3D:
433 case GL_INT_IMAGE_3D:
434 case GL_UNSIGNED_INT_IMAGE_3D:
435 case GL_IMAGE_2D_ARRAY:
436 case GL_INT_IMAGE_2D_ARRAY:
437 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
438 case GL_IMAGE_CUBE:
439 case GL_INT_IMAGE_CUBE:
440 case GL_UNSIGNED_INT_IMAGE_CUBE:
441 return true;
442 }
443 return false;
444}
445
446bool IsImage2DType(GLenum type)
447{
448 switch (type)
449 {
450 case GL_IMAGE_2D:
451 case GL_INT_IMAGE_2D:
452 case GL_UNSIGNED_INT_IMAGE_2D:
453 return true;
454 case GL_IMAGE_3D:
455 case GL_INT_IMAGE_3D:
456 case GL_UNSIGNED_INT_IMAGE_3D:
457 case GL_IMAGE_2D_ARRAY:
458 case GL_INT_IMAGE_2D_ARRAY:
459 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
460 case GL_IMAGE_CUBE:
461 case GL_INT_IMAGE_CUBE:
462 case GL_UNSIGNED_INT_IMAGE_CUBE:
463 return false;
464 default:
465 UNREACHABLE();
466 return false;
467 }
468}
469
470bool IsAtomicCounterType(GLenum type)
471{
472 return type == GL_UNSIGNED_INT_ATOMIC_COUNTER;
473}
474
475bool IsOpaqueType(GLenum type)
476{
477 // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
478 return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
479}
480
481bool IsMatrixType(GLenum type)
482{
483 return VariableRowCount(type) > 1;
484}
485
486GLenum TransposeMatrixType(GLenum type)
487{
488 if (!IsMatrixType(type))
489 {
490 return type;
491 }
492
493 switch (type)
494 {
495 case GL_FLOAT_MAT2:
496 return GL_FLOAT_MAT2;
497 case GL_FLOAT_MAT3:
498 return GL_FLOAT_MAT3;
499 case GL_FLOAT_MAT4:
500 return GL_FLOAT_MAT4;
501 case GL_FLOAT_MAT2x3:
502 return GL_FLOAT_MAT3x2;
503 case GL_FLOAT_MAT3x2:
504 return GL_FLOAT_MAT2x3;
505 case GL_FLOAT_MAT2x4:
506 return GL_FLOAT_MAT4x2;
507 case GL_FLOAT_MAT4x2:
508 return GL_FLOAT_MAT2x4;
509 case GL_FLOAT_MAT3x4:
510 return GL_FLOAT_MAT4x3;
511 case GL_FLOAT_MAT4x3:
512 return GL_FLOAT_MAT3x4;
513 default:
514 UNREACHABLE();
515 return GL_NONE;
516 }
517}
518
519int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix)
520{
521 ASSERT(IsMatrixType(type));
522 return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type);
523}
524
525int MatrixComponentCount(GLenum type, bool isRowMajorMatrix)
526{
527 ASSERT(IsMatrixType(type));
528 return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type);
529}
530
531int VariableRegisterCount(GLenum type)
532{
533 return IsMatrixType(type) ? VariableColumnCount(type) : 1;
534}
535
536int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
537{
538 ASSERT(allocationSize <= bitsSize);
539
540 unsigned int mask = std::numeric_limits<unsigned int>::max() >>
541 (std::numeric_limits<unsigned int>::digits - allocationSize);
542
543 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
544 {
545 if ((*bits & mask) == 0)
546 {
547 *bits |= mask;
548 return i;
549 }
550
551 mask <<= 1;
552 }
553
554 return -1;
555}
556
557IndexRange ComputeIndexRange(DrawElementsType indexType,
558 const GLvoid *indices,
559 size_t count,
560 bool primitiveRestartEnabled)
561{
562 switch (indexType)
563 {
564 case DrawElementsType::UnsignedByte:
565 return ComputeTypedIndexRange(static_cast<const GLubyte *>(indices), count,
566 primitiveRestartEnabled,
567 GetPrimitiveRestartIndex(indexType));
568 case DrawElementsType::UnsignedShort:
569 return ComputeTypedIndexRange(static_cast<const GLushort *>(indices), count,
570 primitiveRestartEnabled,
571 GetPrimitiveRestartIndex(indexType));
572 case DrawElementsType::UnsignedInt:
573 return ComputeTypedIndexRange(static_cast<const GLuint *>(indices), count,
574 primitiveRestartEnabled,
575 GetPrimitiveRestartIndex(indexType));
576 default:
577 UNREACHABLE();
578 return IndexRange();
579 }
580}
581
582GLuint GetPrimitiveRestartIndex(DrawElementsType indexType)
583{
584 switch (indexType)
585 {
586 case DrawElementsType::UnsignedByte:
587 return 0xFF;
588 case DrawElementsType::UnsignedShort:
589 return 0xFFFF;
590 case DrawElementsType::UnsignedInt:
591 return 0xFFFFFFFF;
592 default:
593 UNREACHABLE();
594 return 0;
595 }
596}
597
598bool IsTriangleMode(PrimitiveMode drawMode)
599{
600 switch (drawMode)
601 {
602 case PrimitiveMode::Triangles:
603 case PrimitiveMode::TriangleFan:
604 case PrimitiveMode::TriangleStrip:
605 return true;
606 case PrimitiveMode::Points:
607 case PrimitiveMode::Lines:
608 case PrimitiveMode::LineLoop:
609 case PrimitiveMode::LineStrip:
610 return false;
611 default:
612 UNREACHABLE();
613 }
614
615 return false;
616}
617
618namespace priv
619{
620const angle::PackedEnumMap<PrimitiveMode, bool>& gLineModes()
621{
622 static const angle::PackedEnumMap<PrimitiveMode, bool> modes {
623 { PrimitiveMode::LineLoop, true },
624 { PrimitiveMode::LineStrip, true },
625 { PrimitiveMode::LineStripAdjacency, true },
626 { PrimitiveMode::Lines, true }
627 };
628 return modes;
629};
630} // namespace priv
631
632bool IsIntegerFormat(GLenum unsizedFormat)
633{
634 switch (unsizedFormat)
635 {
636 case GL_RGBA_INTEGER:
637 case GL_RGB_INTEGER:
638 case GL_RG_INTEGER:
639 case GL_RED_INTEGER:
640 return true;
641
642 default:
643 return false;
644 }
645}
646
647// [OpenGL ES SL 3.00.4] Section 11 p. 120
648// Vertex Outs/Fragment Ins packing priorities
649int VariableSortOrder(GLenum type)
650{
651 switch (type)
652 {
653 // 1. Arrays of mat4 and mat4
654 // Non-square matrices of type matCxR consume the same space as a square
655 // matrix of type matN where N is the greater of C and R
656 case GL_FLOAT_MAT4:
657 case GL_FLOAT_MAT2x4:
658 case GL_FLOAT_MAT3x4:
659 case GL_FLOAT_MAT4x2:
660 case GL_FLOAT_MAT4x3:
661 return 0;
662
663 // 2. Arrays of mat2 and mat2 (since they occupy full rows)
664 case GL_FLOAT_MAT2:
665 return 1;
666
667 // 3. Arrays of vec4 and vec4
668 case GL_FLOAT_VEC4:
669 case GL_INT_VEC4:
670 case GL_BOOL_VEC4:
671 case GL_UNSIGNED_INT_VEC4:
672 return 2;
673
674 // 4. Arrays of mat3 and mat3
675 case GL_FLOAT_MAT3:
676 case GL_FLOAT_MAT2x3:
677 case GL_FLOAT_MAT3x2:
678 return 3;
679
680 // 5. Arrays of vec3 and vec3
681 case GL_FLOAT_VEC3:
682 case GL_INT_VEC3:
683 case GL_BOOL_VEC3:
684 case GL_UNSIGNED_INT_VEC3:
685 return 4;
686
687 // 6. Arrays of vec2 and vec2
688 case GL_FLOAT_VEC2:
689 case GL_INT_VEC2:
690 case GL_BOOL_VEC2:
691 case GL_UNSIGNED_INT_VEC2:
692 return 5;
693
694 // 7. Single component types
695 case GL_FLOAT:
696 case GL_INT:
697 case GL_BOOL:
698 case GL_UNSIGNED_INT:
699 case GL_SAMPLER_2D:
700 case GL_SAMPLER_CUBE:
701 case GL_SAMPLER_EXTERNAL_OES:
702 case GL_SAMPLER_2D_RECT_ANGLE:
703 case GL_SAMPLER_2D_ARRAY:
704 case GL_SAMPLER_2D_MULTISAMPLE:
705 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
706 case GL_SAMPLER_3D:
707 case GL_INT_SAMPLER_2D:
708 case GL_INT_SAMPLER_3D:
709 case GL_INT_SAMPLER_CUBE:
710 case GL_INT_SAMPLER_2D_ARRAY:
711 case GL_INT_SAMPLER_2D_MULTISAMPLE:
712 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
713 case GL_UNSIGNED_INT_SAMPLER_2D:
714 case GL_UNSIGNED_INT_SAMPLER_3D:
715 case GL_UNSIGNED_INT_SAMPLER_CUBE:
716 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
717 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
718 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
719 case GL_SAMPLER_2D_SHADOW:
720 case GL_SAMPLER_2D_ARRAY_SHADOW:
721 case GL_SAMPLER_CUBE_SHADOW:
722 case GL_IMAGE_2D:
723 case GL_INT_IMAGE_2D:
724 case GL_UNSIGNED_INT_IMAGE_2D:
725 case GL_IMAGE_3D:
726 case GL_INT_IMAGE_3D:
727 case GL_UNSIGNED_INT_IMAGE_3D:
728 case GL_IMAGE_2D_ARRAY:
729 case GL_INT_IMAGE_2D_ARRAY:
730 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
731 case GL_IMAGE_CUBE:
732 case GL_INT_IMAGE_CUBE:
733 case GL_UNSIGNED_INT_IMAGE_CUBE:
734 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
735 return 6;
736
737 default:
738 UNREACHABLE();
739 return 0;
740 }
741}
742
743std::string ParseResourceName(const std::string &name, std::vector<unsigned int> *outSubscripts)
744{
745 if (outSubscripts)
746 {
747 outSubscripts->clear();
748 }
749 // Strip any trailing array indexing operators and retrieve the subscripts.
750 size_t baseNameLength = name.length();
751 bool hasIndex = true;
752 while (hasIndex)
753 {
754 size_t open = name.find_last_of('[', baseNameLength - 1);
755 size_t close = name.find_last_of(']', baseNameLength - 1);
756 hasIndex = (open != std::string::npos) && (close == baseNameLength - 1);
757 if (hasIndex)
758 {
759 baseNameLength = open;
760 if (outSubscripts)
761 {
762 int index = atoi(name.substr(open + 1).c_str());
763 if (index >= 0)
764 {
765 outSubscripts->push_back(index);
766 }
767 else
768 {
769 outSubscripts->push_back(GL_INVALID_INDEX);
770 }
771 }
772 }
773 }
774
775 return name.substr(0, baseNameLength);
776}
777
778const sh::ShaderVariable *FindShaderVarField(const sh::ShaderVariable &var,
779 const std::string &fullName)
780{
781 if (var.fields.empty())
782 {
783 return nullptr;
784 }
785 size_t pos = fullName.find_first_of(".");
786 if (pos == std::string::npos)
787 {
788 return nullptr;
789 }
790 std::string topName = fullName.substr(0, pos);
791 if (topName != var.name)
792 {
793 return nullptr;
794 }
795 std::string fieldName = fullName.substr(pos + 1);
796 if (fieldName.empty())
797 {
798 return nullptr;
799 }
800 for (const auto &field : var.fields)
801 {
802 if (field.name == fieldName)
803 {
804 return &field;
805 }
806 }
807 return nullptr;
808}
809
810unsigned int ArraySizeProduct(const std::vector<unsigned int> &arraySizes)
811{
812 unsigned int arraySizeProduct = 1u;
813 for (unsigned int arraySize : arraySizes)
814 {
815 arraySizeProduct *= arraySize;
816 }
817 return arraySizeProduct;
818}
819
820unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut)
821{
822 ASSERT(nameLengthWithoutArrayIndexOut != nullptr);
823
824 // Strip any trailing array operator and retrieve the subscript
825 size_t open = name.find_last_of('[');
826 if (open != std::string::npos && name.back() == ']')
827 {
828 bool indexIsValidDecimalNumber = true;
829 for (size_t i = open + 1; i < name.length() - 1u; ++i)
830 {
831 if (!isdigit(name[i]))
832 {
833 indexIsValidDecimalNumber = false;
834 break;
835 }
836 }
837 if (indexIsValidDecimalNumber)
838 {
839 errno = 0; // reset global error flag.
840 unsigned long subscript =
841 strtoul(name.c_str() + open + 1, /*endptr*/ nullptr, /*radix*/ 10);
842
843 // Check if resulting integer is out-of-range or conversion error.
844 if ((subscript <= static_cast<unsigned long>(UINT_MAX)) &&
845 !(subscript == ULONG_MAX && errno == ERANGE) && !(errno != 0 && subscript == 0))
846 {
847 *nameLengthWithoutArrayIndexOut = open;
848 return static_cast<unsigned int>(subscript);
849 }
850 }
851 }
852
853 *nameLengthWithoutArrayIndexOut = name.length();
854 return GL_INVALID_INDEX;
855}
856
857const char *GetGenericErrorMessage(GLenum error)
858{
859 switch (error)
860 {
861 case GL_NO_ERROR:
862 return "";
863 case GL_INVALID_ENUM:
864 return "Invalid enum.";
865 case GL_INVALID_VALUE:
866 return "Invalid value.";
867 case GL_INVALID_OPERATION:
868 return "Invalid operation.";
869 case GL_STACK_OVERFLOW:
870 return "Stack overflow.";
871 case GL_STACK_UNDERFLOW:
872 return "Stack underflow.";
873 case GL_OUT_OF_MEMORY:
874 return "Out of memory.";
875 case GL_INVALID_FRAMEBUFFER_OPERATION:
876 return "Invalid framebuffer operation.";
877 default:
878 UNREACHABLE();
879 return "Unknown error.";
880 }
881}
882
883unsigned int ElementTypeSize(GLenum elementType)
884{
885 switch (elementType)
886 {
887 case GL_UNSIGNED_BYTE:
888 return sizeof(GLubyte);
889 case GL_UNSIGNED_SHORT:
890 return sizeof(GLushort);
891 case GL_UNSIGNED_INT:
892 return sizeof(GLuint);
893 default:
894 UNREACHABLE();
895 return 0;
896 }
897}
898
899} // namespace gl
900
901namespace egl
902{
903static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
904 "Unexpected EGL cube map enum value.");
905static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2,
906 "Unexpected EGL cube map enum value.");
907static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3,
908 "Unexpected EGL cube map enum value.");
909static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4,
910 "Unexpected EGL cube map enum value.");
911static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5,
912 "Unexpected EGL cube map enum value.");
913
914bool IsCubeMapTextureTarget(EGLenum target)
915{
916 return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
917}
918
919size_t CubeMapTextureTargetToLayerIndex(EGLenum target)
920{
921 ASSERT(IsCubeMapTextureTarget(target));
922 return target - static_cast<size_t>(FirstCubeMapTextureTarget);
923}
924
925EGLenum LayerIndexToCubeMapTextureTarget(size_t index)
926{
927 ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
928 return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
929}
930
931bool IsTextureTarget(EGLenum target)
932{
933 switch (target)
934 {
935 case EGL_GL_TEXTURE_2D_KHR:
936 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
937 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
938 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
939 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
940 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
941 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
942 case EGL_GL_TEXTURE_3D_KHR:
943 return true;
944
945 default:
946 return false;
947 }
948}
949
950bool IsRenderbufferTarget(EGLenum target)
951{
952 return target == EGL_GL_RENDERBUFFER_KHR;
953}
954
955bool IsExternalImageTarget(EGLenum target)
956{
957 switch (target)
958 {
959 case EGL_NATIVE_BUFFER_ANDROID:
960 return true;
961
962 default:
963 return false;
964 }
965}
966
967const char *GetGenericErrorMessage(EGLint error)
968{
969 switch (error)
970 {
971 case EGL_SUCCESS:
972 return "";
973 case EGL_NOT_INITIALIZED:
974 return "Not initialized.";
975 case EGL_BAD_ACCESS:
976 return "Bad access.";
977 case EGL_BAD_ALLOC:
978 return "Bad allocation.";
979 case EGL_BAD_ATTRIBUTE:
980 return "Bad attribute.";
981 case EGL_BAD_CONFIG:
982 return "Bad config.";
983 case EGL_BAD_CONTEXT:
984 return "Bad context.";
985 case EGL_BAD_CURRENT_SURFACE:
986 return "Bad current surface.";
987 case EGL_BAD_DISPLAY:
988 return "Bad display.";
989 case EGL_BAD_MATCH:
990 return "Bad match.";
991 case EGL_BAD_NATIVE_WINDOW:
992 return "Bad native window.";
993 case EGL_BAD_PARAMETER:
994 return "Bad parameter.";
995 case EGL_BAD_SURFACE:
996 return "Bad surface.";
997 case EGL_CONTEXT_LOST:
998 return "Context lost.";
999 case EGL_BAD_STREAM_KHR:
1000 return "Bad stream.";
1001 case EGL_BAD_STATE_KHR:
1002 return "Bad state.";
1003 case EGL_BAD_DEVICE_EXT:
1004 return "Bad device.";
1005 default:
1006 UNREACHABLE();
1007 return "Unknown error.";
1008 }
1009}
1010
1011} // namespace egl
1012
1013namespace egl_gl
1014{
1015GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
1016{
1017 return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
1018}
1019} // namespace egl_gl
1020
1021namespace gl_egl
1022{
1023EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType)
1024{
1025 switch (glComponentType)
1026 {
1027 case GL_FLOAT:
1028 return EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
1029
1030 case GL_UNSIGNED_NORMALIZED:
1031 return EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
1032
1033 default:
1034 UNREACHABLE();
1035 return EGL_NONE;
1036 }
1037}
1038
1039EGLClientBuffer GLObjectHandleToEGLClientBuffer(GLuint handle)
1040{
1041 return reinterpret_cast<EGLClientBuffer>(static_cast<uintptr_t>(handle));
1042}
1043
1044} // namespace gl_egl
1045
1046#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
1047std::string getTempPath()
1048{
1049# ifdef ANGLE_PLATFORM_WINDOWS
1050 char path[MAX_PATH];
1051 DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
1052 if (pathLen == 0)
1053 {
1054 UNREACHABLE();
1055 return std::string();
1056 }
1057
1058 UINT unique = GetTempFileNameA(path, "sh", 0, path);
1059 if (unique == 0)
1060 {
1061 UNREACHABLE();
1062 return std::string();
1063 }
1064
1065 return path;
1066# else
1067 UNIMPLEMENTED();
1068 return "";
1069# endif
1070}
1071
1072void writeFile(const char *path, const void *content, size_t size)
1073{
1074 FILE *file = fopen(path, "w");
1075 if (!file)
1076 {
1077 UNREACHABLE();
1078 return;
1079 }
1080
1081 fwrite(content, sizeof(char), size, file);
1082 fclose(file);
1083}
1084#endif // !ANGLE_ENABLE_WINDOWS_STORE
1085
1086#if defined(ANGLE_PLATFORM_WINDOWS)
1087
1088// Causes the thread to relinquish the remainder of its time slice to any
1089// other thread that is ready to run.If there are no other threads ready
1090// to run, the function returns immediately, and the thread continues execution.
1091void ScheduleYield()
1092{
1093 Sleep(0);
1094}
1095
1096#endif
1097