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