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_3D:
128       case GL_SAMPLER_CUBE:
129       case GL_SAMPLER_2D_ARRAY:
130       case GL_SAMPLER_EXTERNAL_OES:
131       case GL_INT_SAMPLER_2D:
132       case GL_INT_SAMPLER_3D:
133       case GL_INT_SAMPLER_CUBE:
134       case GL_INT_SAMPLER_2D_ARRAY:
135       case GL_UNSIGNED_INT_SAMPLER_2D:
136       case GL_UNSIGNED_INT_SAMPLER_3D:
137       case GL_UNSIGNED_INT_SAMPLER_CUBE:
138       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
139       case GL_SAMPLER_2D_SHADOW:
140       case GL_SAMPLER_CUBE_SHADOW:
141       case GL_SAMPLER_2D_ARRAY_SHADOW:
142       case GL_INT_VEC2:
143       case GL_INT_VEC3:
144       case GL_INT_VEC4:
145         return GL_INT;
146       case GL_UNSIGNED_INT:
147       case GL_UNSIGNED_INT_VEC2:
148       case GL_UNSIGNED_INT_VEC3:
149       case GL_UNSIGNED_INT_VEC4:
150         return GL_UNSIGNED_INT;
151       default:
152         UNREACHABLE();
153     }
154 
155     return GL_NONE;
156 }
157 
VariableComponentSize(GLenum type)158 size_t VariableComponentSize(GLenum type)
159 {
160     switch(type)
161     {
162       case GL_BOOL:         return sizeof(GLint);
163       case GL_FLOAT:        return sizeof(GLfloat);
164       case GL_INT:          return sizeof(GLint);
165       case GL_UNSIGNED_INT: return sizeof(GLuint);
166       default:       UNREACHABLE();
167     }
168 
169     return 0;
170 }
171 
VariableInternalSize(GLenum type)172 size_t VariableInternalSize(GLenum type)
173 {
174     // Expanded to 4-element vectors
175     return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4;
176 }
177 
VariableExternalSize(GLenum type)178 size_t VariableExternalSize(GLenum type)
179 {
180     return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type);
181 }
182 
VariableBoolVectorType(GLenum type)183 GLenum VariableBoolVectorType(GLenum type)
184 {
185     switch (type)
186     {
187       case GL_FLOAT:
188       case GL_INT:
189       case GL_UNSIGNED_INT:
190         return GL_BOOL;
191       case GL_FLOAT_VEC2:
192       case GL_INT_VEC2:
193       case GL_UNSIGNED_INT_VEC2:
194         return GL_BOOL_VEC2;
195       case GL_FLOAT_VEC3:
196       case GL_INT_VEC3:
197       case GL_UNSIGNED_INT_VEC3:
198         return GL_BOOL_VEC3;
199       case GL_FLOAT_VEC4:
200       case GL_INT_VEC4:
201       case GL_UNSIGNED_INT_VEC4:
202         return GL_BOOL_VEC4;
203 
204       default:
205         UNREACHABLE();
206         return GL_NONE;
207     }
208 }
209 
VariableRowCount(GLenum type)210 int VariableRowCount(GLenum type)
211 {
212     switch (type)
213     {
214       case GL_NONE:
215       case GL_STRUCT_ANGLEX:
216         return 0;
217       case GL_BOOL:
218       case GL_FLOAT:
219       case GL_INT:
220       case GL_UNSIGNED_INT:
221       case GL_BOOL_VEC2:
222       case GL_FLOAT_VEC2:
223       case GL_INT_VEC2:
224       case GL_UNSIGNED_INT_VEC2:
225       case GL_BOOL_VEC3:
226       case GL_FLOAT_VEC3:
227       case GL_INT_VEC3:
228       case GL_UNSIGNED_INT_VEC3:
229       case GL_BOOL_VEC4:
230       case GL_FLOAT_VEC4:
231       case GL_INT_VEC4:
232       case GL_UNSIGNED_INT_VEC4:
233       case GL_SAMPLER_2D:
234       case GL_SAMPLER_3D:
235       case GL_SAMPLER_CUBE:
236       case GL_SAMPLER_2D_ARRAY:
237       case GL_SAMPLER_EXTERNAL_OES:
238       case GL_SAMPLER_2D_RECT_ARB:
239       case GL_INT_SAMPLER_2D:
240       case GL_INT_SAMPLER_3D:
241       case GL_INT_SAMPLER_CUBE:
242       case GL_INT_SAMPLER_2D_ARRAY:
243       case GL_UNSIGNED_INT_SAMPLER_2D:
244       case GL_UNSIGNED_INT_SAMPLER_3D:
245       case GL_UNSIGNED_INT_SAMPLER_CUBE:
246       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
247       case GL_SAMPLER_2D_SHADOW:
248       case GL_SAMPLER_CUBE_SHADOW:
249       case GL_SAMPLER_2D_ARRAY_SHADOW:
250       case GL_IMAGE_2D:
251       case GL_INT_IMAGE_2D:
252       case GL_UNSIGNED_INT_IMAGE_2D:
253       case GL_IMAGE_2D_ARRAY:
254       case GL_INT_IMAGE_2D_ARRAY:
255       case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
256       case GL_IMAGE_3D:
257       case GL_INT_IMAGE_3D:
258       case GL_UNSIGNED_INT_IMAGE_3D:
259       case GL_IMAGE_CUBE:
260       case GL_INT_IMAGE_CUBE:
261       case GL_UNSIGNED_INT_IMAGE_CUBE:
262           return 1;
263       case GL_FLOAT_MAT2:
264       case GL_FLOAT_MAT3x2:
265       case GL_FLOAT_MAT4x2:
266         return 2;
267       case GL_FLOAT_MAT3:
268       case GL_FLOAT_MAT2x3:
269       case GL_FLOAT_MAT4x3:
270         return 3;
271       case GL_FLOAT_MAT4:
272       case GL_FLOAT_MAT2x4:
273       case GL_FLOAT_MAT3x4:
274         return 4;
275       default:
276         UNREACHABLE();
277     }
278 
279     return 0;
280 }
281 
VariableColumnCount(GLenum type)282 int VariableColumnCount(GLenum type)
283 {
284     switch (type)
285     {
286       case GL_NONE:
287       case GL_STRUCT_ANGLEX:
288         return 0;
289       case GL_BOOL:
290       case GL_FLOAT:
291       case GL_INT:
292       case GL_UNSIGNED_INT:
293       case GL_SAMPLER_2D:
294       case GL_SAMPLER_3D:
295       case GL_SAMPLER_CUBE:
296       case GL_SAMPLER_2D_ARRAY:
297       case GL_INT_SAMPLER_2D:
298       case GL_INT_SAMPLER_3D:
299       case GL_INT_SAMPLER_CUBE:
300       case GL_INT_SAMPLER_2D_ARRAY:
301       case GL_SAMPLER_EXTERNAL_OES:
302       case GL_SAMPLER_2D_RECT_ARB:
303       case GL_UNSIGNED_INT_SAMPLER_2D:
304       case GL_UNSIGNED_INT_SAMPLER_3D:
305       case GL_UNSIGNED_INT_SAMPLER_CUBE:
306       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
307       case GL_SAMPLER_2D_SHADOW:
308       case GL_SAMPLER_CUBE_SHADOW:
309       case GL_SAMPLER_2D_ARRAY_SHADOW:
310         return 1;
311       case GL_BOOL_VEC2:
312       case GL_FLOAT_VEC2:
313       case GL_INT_VEC2:
314       case GL_UNSIGNED_INT_VEC2:
315       case GL_FLOAT_MAT2:
316       case GL_FLOAT_MAT2x3:
317       case GL_FLOAT_MAT2x4:
318         return 2;
319       case GL_BOOL_VEC3:
320       case GL_FLOAT_VEC3:
321       case GL_INT_VEC3:
322       case GL_UNSIGNED_INT_VEC3:
323       case GL_FLOAT_MAT3:
324       case GL_FLOAT_MAT3x2:
325       case GL_FLOAT_MAT3x4:
326         return 3;
327       case GL_BOOL_VEC4:
328       case GL_FLOAT_VEC4:
329       case GL_INT_VEC4:
330       case GL_UNSIGNED_INT_VEC4:
331       case GL_FLOAT_MAT4:
332       case GL_FLOAT_MAT4x2:
333       case GL_FLOAT_MAT4x3:
334         return 4;
335       default:
336         UNREACHABLE();
337     }
338 
339     return 0;
340 }
341 
IsSamplerType(GLenum type)342 bool IsSamplerType(GLenum type)
343 {
344     switch (type)
345     {
346       case GL_SAMPLER_2D:
347       case GL_SAMPLER_3D:
348       case GL_SAMPLER_CUBE:
349       case GL_SAMPLER_2D_ARRAY:
350       case GL_SAMPLER_EXTERNAL_OES:
351       case GL_INT_SAMPLER_2D:
352       case GL_INT_SAMPLER_3D:
353       case GL_INT_SAMPLER_CUBE:
354       case GL_INT_SAMPLER_2D_ARRAY:
355       case GL_UNSIGNED_INT_SAMPLER_2D:
356       case GL_UNSIGNED_INT_SAMPLER_3D:
357       case GL_UNSIGNED_INT_SAMPLER_CUBE:
358       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
359       case GL_SAMPLER_2D_SHADOW:
360       case GL_SAMPLER_CUBE_SHADOW:
361       case GL_SAMPLER_2D_ARRAY_SHADOW:
362         return true;
363     }
364 
365     return false;
366 }
367 
SamplerTypeToTextureType(GLenum samplerType)368 GLenum SamplerTypeToTextureType(GLenum samplerType)
369 {
370     switch (samplerType)
371     {
372       case GL_SAMPLER_2D:
373       case GL_INT_SAMPLER_2D:
374       case GL_UNSIGNED_INT_SAMPLER_2D:
375       case GL_SAMPLER_2D_SHADOW:
376         return GL_TEXTURE_2D;
377 
378       case GL_SAMPLER_EXTERNAL_OES:
379           return GL_TEXTURE_EXTERNAL_OES;
380 
381       case GL_SAMPLER_CUBE:
382       case GL_INT_SAMPLER_CUBE:
383       case GL_UNSIGNED_INT_SAMPLER_CUBE:
384       case GL_SAMPLER_CUBE_SHADOW:
385         return GL_TEXTURE_CUBE_MAP;
386 
387       case GL_SAMPLER_2D_ARRAY:
388       case GL_INT_SAMPLER_2D_ARRAY:
389       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
390       case GL_SAMPLER_2D_ARRAY_SHADOW:
391         return GL_TEXTURE_2D_ARRAY;
392 
393       case GL_SAMPLER_3D:
394       case GL_INT_SAMPLER_3D:
395       case GL_UNSIGNED_INT_SAMPLER_3D:
396         return GL_TEXTURE_3D;
397 
398       default:
399         UNREACHABLE();
400         return 0;
401     }
402 }
403 
IsMatrixType(GLenum type)404 bool IsMatrixType(GLenum type)
405 {
406     return VariableRowCount(type) > 1;
407 }
408 
TransposeMatrixType(GLenum type)409 GLenum TransposeMatrixType(GLenum type)
410 {
411     if (!IsMatrixType(type))
412     {
413         return type;
414     }
415 
416     switch (type)
417     {
418       case GL_FLOAT_MAT2:   return GL_FLOAT_MAT2;
419       case GL_FLOAT_MAT3:   return GL_FLOAT_MAT3;
420       case GL_FLOAT_MAT4:   return GL_FLOAT_MAT4;
421       case GL_FLOAT_MAT2x3: return GL_FLOAT_MAT3x2;
422       case GL_FLOAT_MAT3x2: return GL_FLOAT_MAT2x3;
423       case GL_FLOAT_MAT2x4: return GL_FLOAT_MAT4x2;
424       case GL_FLOAT_MAT4x2: return GL_FLOAT_MAT2x4;
425       case GL_FLOAT_MAT3x4: return GL_FLOAT_MAT4x3;
426       case GL_FLOAT_MAT4x3: return GL_FLOAT_MAT3x4;
427       default: UNREACHABLE(); return GL_NONE;
428     }
429 }
430 
MatrixRegisterCount(GLenum type,bool isRowMajorMatrix)431 int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix)
432 {
433     ASSERT(IsMatrixType(type));
434     return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type);
435 }
436 
MatrixComponentCount(GLenum type,bool isRowMajorMatrix)437 int MatrixComponentCount(GLenum type, bool isRowMajorMatrix)
438 {
439     ASSERT(IsMatrixType(type));
440     return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type);
441 }
442 
VariableRegisterCount(GLenum type)443 int VariableRegisterCount(GLenum type)
444 {
445     return IsMatrixType(type) ? VariableColumnCount(type) : 1;
446 }
447 
AllocateFirstFreeBits(unsigned int * bits,unsigned int allocationSize,unsigned int bitsSize)448 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
449 {
450     ASSERT(allocationSize <= bitsSize);
451 
452     unsigned int mask = std::numeric_limits<unsigned int>::max() >> (std::numeric_limits<unsigned int>::digits - allocationSize);
453 
454     for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
455     {
456         if ((*bits & mask) == 0)
457         {
458             *bits |= mask;
459             return i;
460         }
461 
462         mask <<= 1;
463     }
464 
465     return -1;
466 }
467 
468 static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
469 static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
470 static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
471 static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
472 static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
473 
IsCubeMapTextureTarget(GLenum target)474 bool IsCubeMapTextureTarget(GLenum target)
475 {
476     return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
477 }
478 
CubeMapTextureTargetToLayerIndex(GLenum target)479 size_t CubeMapTextureTargetToLayerIndex(GLenum target)
480 {
481     ASSERT(IsCubeMapTextureTarget(target));
482     return target - static_cast<size_t>(FirstCubeMapTextureTarget);
483 }
484 
LayerIndexToCubeMapTextureTarget(size_t index)485 GLenum LayerIndexToCubeMapTextureTarget(size_t index)
486 {
487     ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
488     return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
489 }
490 
ComputeIndexRange(GLenum indexType,const GLvoid * indices,size_t count,bool primitiveRestartEnabled)491 IndexRange ComputeIndexRange(GLenum indexType,
492                              const GLvoid *indices,
493                              size_t count,
494                              bool primitiveRestartEnabled)
495 {
496     switch (indexType)
497     {
498         case GL_UNSIGNED_BYTE:
499             return ComputeTypedIndexRange(static_cast<const GLubyte *>(indices), count,
500                                           primitiveRestartEnabled,
501                                           GetPrimitiveRestartIndex(indexType));
502         case GL_UNSIGNED_SHORT:
503             return ComputeTypedIndexRange(static_cast<const GLushort *>(indices), count,
504                                           primitiveRestartEnabled,
505                                           GetPrimitiveRestartIndex(indexType));
506         case GL_UNSIGNED_INT:
507             return ComputeTypedIndexRange(static_cast<const GLuint *>(indices), count,
508                                           primitiveRestartEnabled,
509                                           GetPrimitiveRestartIndex(indexType));
510         default:
511             UNREACHABLE();
512             return IndexRange();
513     }
514 }
515 
GetPrimitiveRestartIndex(GLenum indexType)516 GLuint GetPrimitiveRestartIndex(GLenum indexType)
517 {
518     switch (indexType)
519     {
520         case GL_UNSIGNED_BYTE:
521             return 0xFF;
522         case GL_UNSIGNED_SHORT:
523             return 0xFFFF;
524         case GL_UNSIGNED_INT:
525             return 0xFFFFFFFF;
526         default:
527             UNREACHABLE();
528             return 0;
529     }
530 }
531 
IsTriangleMode(GLenum drawMode)532 bool IsTriangleMode(GLenum drawMode)
533 {
534     switch (drawMode)
535     {
536       case GL_TRIANGLES:
537       case GL_TRIANGLE_FAN:
538       case GL_TRIANGLE_STRIP:
539         return true;
540       case GL_POINTS:
541       case GL_LINES:
542       case GL_LINE_LOOP:
543       case GL_LINE_STRIP:
544         return false;
545       default: UNREACHABLE();
546     }
547 
548     return false;
549 }
550 
551 // [OpenGL ES SL 3.00.4] Section 11 p. 120
552 // Vertex Outs/Fragment Ins packing priorities
VariableSortOrder(GLenum type)553 int VariableSortOrder(GLenum type)
554 {
555     switch (type)
556     {
557       // 1. Arrays of mat4 and mat4
558       // Non-square matrices of type matCxR consume the same space as a square
559       // matrix of type matN where N is the greater of C and R
560       case GL_FLOAT_MAT4:
561       case GL_FLOAT_MAT2x4:
562       case GL_FLOAT_MAT3x4:
563       case GL_FLOAT_MAT4x2:
564       case GL_FLOAT_MAT4x3:
565         return 0;
566 
567       // 2. Arrays of mat2 and mat2 (since they occupy full rows)
568       case GL_FLOAT_MAT2:
569         return 1;
570 
571       // 3. Arrays of vec4 and vec4
572       case GL_FLOAT_VEC4:
573       case GL_INT_VEC4:
574       case GL_BOOL_VEC4:
575       case GL_UNSIGNED_INT_VEC4:
576         return 2;
577 
578       // 4. Arrays of mat3 and mat3
579       case GL_FLOAT_MAT3:
580       case GL_FLOAT_MAT2x3:
581       case GL_FLOAT_MAT3x2:
582         return 3;
583 
584       // 5. Arrays of vec3 and vec3
585       case GL_FLOAT_VEC3:
586       case GL_INT_VEC3:
587       case GL_BOOL_VEC3:
588       case GL_UNSIGNED_INT_VEC3:
589         return 4;
590 
591       // 6. Arrays of vec2 and vec2
592       case GL_FLOAT_VEC2:
593       case GL_INT_VEC2:
594       case GL_BOOL_VEC2:
595       case GL_UNSIGNED_INT_VEC2:
596         return 5;
597 
598       // 7. Single component types
599       case GL_FLOAT:
600       case GL_INT:
601       case GL_BOOL:
602       case GL_UNSIGNED_INT:
603       case GL_SAMPLER_2D:
604       case GL_SAMPLER_CUBE:
605       case GL_SAMPLER_EXTERNAL_OES:
606       case GL_SAMPLER_2D_RECT_ARB:
607       case GL_SAMPLER_2D_ARRAY:
608       case GL_SAMPLER_3D:
609       case GL_INT_SAMPLER_2D:
610       case GL_INT_SAMPLER_3D:
611       case GL_INT_SAMPLER_CUBE:
612       case GL_INT_SAMPLER_2D_ARRAY:
613       case GL_UNSIGNED_INT_SAMPLER_2D:
614       case GL_UNSIGNED_INT_SAMPLER_3D:
615       case GL_UNSIGNED_INT_SAMPLER_CUBE:
616       case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
617       case GL_SAMPLER_2D_SHADOW:
618       case GL_SAMPLER_2D_ARRAY_SHADOW:
619       case GL_SAMPLER_CUBE_SHADOW:
620         return 6;
621 
622       default:
623         UNREACHABLE();
624         return 0;
625     }
626 }
627 
ParseUniformName(const std::string & name,size_t * outSubscript)628 std::string ParseUniformName(const std::string &name, size_t *outSubscript)
629 {
630     // Strip any trailing array operator and retrieve the subscript
631     size_t open = name.find_last_of('[');
632     size_t close = name.find_last_of(']');
633     bool hasIndex = (open != std::string::npos) && (close == name.length() - 1);
634     if (!hasIndex)
635     {
636         if (outSubscript)
637         {
638             *outSubscript = GL_INVALID_INDEX;
639         }
640         return name;
641     }
642 
643     if (outSubscript)
644     {
645         int index = atoi(name.substr(open + 1).c_str());
646         if (index >= 0)
647         {
648             *outSubscript = index;
649         }
650         else
651         {
652             *outSubscript = GL_INVALID_INDEX;
653         }
654     }
655 
656     return name.substr(0, open);
657 }
658 
659 template <>
ConvertToGLuint(GLfloat param)660 GLuint ConvertToGLuint(GLfloat param)
661 {
662     return uiround<GLuint>(param);
663 }
664 
665 template <>
ConvertToGLint(GLfloat param)666 GLint ConvertToGLint(GLfloat param)
667 {
668     return iround<GLint>(param);
669 }
670 
671 template <>
ConvertFromGLfloat(GLfloat param)672 GLint ConvertFromGLfloat(GLfloat param)
673 {
674     return iround<GLint>(param);
675 }
676 template <>
ConvertFromGLfloat(GLfloat param)677 GLuint ConvertFromGLfloat(GLfloat param)
678 {
679     return uiround<GLuint>(param);
680 }
681 
ParseAndStripArrayIndex(std::string * name)682 unsigned int ParseAndStripArrayIndex(std::string *name)
683 {
684     unsigned int subscript = GL_INVALID_INDEX;
685 
686     // Strip any trailing array operator and retrieve the subscript
687     size_t open  = name->find_last_of('[');
688     size_t close = name->find_last_of(']');
689     if (open != std::string::npos && close == name->length() - 1)
690     {
691         subscript = atoi(name->c_str() + open + 1);
692         name->erase(open);
693     }
694 
695     return subscript;
696 }
697 
698 }  // namespace gl
699 
700 namespace egl
701 {
702 static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
703               "Unexpected EGL cube map enum value.");
704 static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2,
705               "Unexpected EGL cube map enum value.");
706 static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3,
707               "Unexpected EGL cube map enum value.");
708 static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4,
709               "Unexpected EGL cube map enum value.");
710 static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5,
711               "Unexpected EGL cube map enum value.");
712 
IsCubeMapTextureTarget(EGLenum target)713 bool IsCubeMapTextureTarget(EGLenum target)
714 {
715     return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
716 }
717 
CubeMapTextureTargetToLayerIndex(EGLenum target)718 size_t CubeMapTextureTargetToLayerIndex(EGLenum target)
719 {
720     ASSERT(IsCubeMapTextureTarget(target));
721     return target - static_cast<size_t>(FirstCubeMapTextureTarget);
722 }
723 
LayerIndexToCubeMapTextureTarget(size_t index)724 EGLenum LayerIndexToCubeMapTextureTarget(size_t index)
725 {
726     ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
727     return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
728 }
729 
IsTextureTarget(EGLenum target)730 bool IsTextureTarget(EGLenum target)
731 {
732     switch (target)
733     {
734         case EGL_GL_TEXTURE_2D_KHR:
735         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
736         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
737         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
738         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
739         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
740         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
741         case EGL_GL_TEXTURE_3D_KHR:
742             return true;
743 
744         default:
745             return false;
746     }
747 }
748 
IsRenderbufferTarget(EGLenum target)749 bool IsRenderbufferTarget(EGLenum target)
750 {
751     return target == EGL_GL_RENDERBUFFER_KHR;
752 }
753 }  // namespace egl
754 
755 namespace egl_gl
756 {
EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)757 GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
758 {
759     ASSERT(egl::IsCubeMapTextureTarget(eglTarget));
760     return gl::LayerIndexToCubeMapTextureTarget(egl::CubeMapTextureTargetToLayerIndex(eglTarget));
761 }
762 
EGLImageTargetToGLTextureTarget(EGLenum eglTarget)763 GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget)
764 {
765     switch (eglTarget)
766     {
767         case EGL_GL_TEXTURE_2D_KHR:
768             return GL_TEXTURE_2D;
769 
770         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
771         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
772         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
773         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
774         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
775         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
776             return EGLCubeMapTargetToGLCubeMapTarget(eglTarget);
777 
778         case EGL_GL_TEXTURE_3D_KHR:
779             return GL_TEXTURE_3D;
780 
781         default:
782             UNREACHABLE();
783             return GL_NONE;
784     }
785 }
786 
EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)787 GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
788 {
789     return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
790 }
791 }  // namespace egl_gl
792 
793 #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
getTempPath()794 std::string getTempPath()
795 {
796 #ifdef ANGLE_PLATFORM_WINDOWS
797     char path[MAX_PATH];
798     DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
799     if (pathLen == 0)
800     {
801         UNREACHABLE();
802         return std::string();
803     }
804 
805     UINT unique = GetTempFileNameA(path, "sh", 0, path);
806     if (unique == 0)
807     {
808         UNREACHABLE();
809         return std::string();
810     }
811 
812     return path;
813 #else
814     UNIMPLEMENTED();
815     return "";
816 #endif
817 }
818 
writeFile(const char * path,const void * content,size_t size)819 void writeFile(const char* path, const void* content, size_t size)
820 {
821     FILE* file = fopen(path, "w");
822     if (!file)
823     {
824         UNREACHABLE();
825         return;
826     }
827 
828     fwrite(content, sizeof(char), size, file);
829     fclose(file);
830 }
831 #endif // !ANGLE_ENABLE_WINDOWS_STORE
832 
833 #if defined (ANGLE_PLATFORM_WINDOWS)
834 
835 // Causes the thread to relinquish the remainder of its time slice to any
836 // other thread that is ready to run.If there are no other threads ready
837 // to run, the function returns immediately, and the thread continues execution.
ScheduleYield()838 void ScheduleYield()
839 {
840     Sleep(0);
841 }
842 
843 #endif
844