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