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