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