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