blob: 460845cfe543719e3c9af27dc94a0174d7bb1548 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// 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
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +00009#include "common/utilities.h"
jchen108225e732017-11-14 16:29:03 +080010#include <GLSLANG/ShaderVars.h>
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000011#include "common/mathutil.h"
Geoff Lang44fa7592014-05-30 11:50:07 -040012#include "common/platform.h"
Geoff Lang83217792014-01-16 09:52:38 -050013
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000014#include <set>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000015
Cooper Partin88d3b8c2014-10-08 10:41:56 -070016#if defined(ANGLE_ENABLE_WINDOWS_STORE)
Jamie Madill493f9572018-05-24 19:52:15 -040017#include <windows.applicationmodel.core.h>
18#include <windows.graphics.display.h>
19#include <wrl.h>
20#include <wrl/wrappers/corewrappers.h>
Cooper Partin88d3b8c2014-10-08 10:41:56 -070021#endif
22
Geoff Lang3edfe032015-09-04 16:38:24 -040023namespace
24{
25
26template <class IndexType>
27gl::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
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000095namespace gl
96{
97
Jamie Madillf2575982014-06-25 16:04:54 -040098int VariableComponentCount(GLenum type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000099{
Jamie Madillaa72d782014-07-02 15:31:19 -0400100 return VariableRowCount(type) * VariableColumnCount(type);
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000101}
102
Jamie Madillf2575982014-06-25 16:04:54 -0400103GLenum VariableComponentType(GLenum type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000104{
Jamie Madill493f9572018-05-24 19:52:15 -0400105 switch (type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000106 {
Jamie Madill493f9572018-05-24 19:52:15 -0400107 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();
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000171 }
172
173 return GL_NONE;
174}
175
Jamie Madillf2575982014-06-25 16:04:54 -0400176size_t VariableComponentSize(GLenum type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000177{
Jamie Madill493f9572018-05-24 19:52:15 -0400178 switch (type)
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000179 {
Jamie Madill493f9572018-05-24 19:52:15 -0400180 case GL_BOOL:
181 return sizeof(GLint);
182 case GL_FLOAT:
183 return sizeof(GLfloat);
184 case GL_INT:
185 return sizeof(GLint);
186 case GL_UNSIGNED_INT:
187 return sizeof(GLuint);
188 default:
189 UNREACHABLE();
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000190 }
191
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000192 return 0;
193}
194
Jamie Madillf2575982014-06-25 16:04:54 -0400195size_t VariableInternalSize(GLenum type)
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000196{
shannon.woods@transgaming.com2494c972013-02-28 23:10:03 +0000197 // Expanded to 4-element vectors
Jamie Madillf2575982014-06-25 16:04:54 -0400198 return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000199}
200
Jamie Madillf2575982014-06-25 16:04:54 -0400201size_t VariableExternalSize(GLenum type)
daniel@transgaming.com47c60052011-11-12 03:17:50 +0000202{
Jamie Madillf2575982014-06-25 16:04:54 -0400203 return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type);
daniel@transgaming.com47c60052011-11-12 03:17:50 +0000204}
205
Jamie Madillf2575982014-06-25 16:04:54 -0400206GLenum VariableBoolVectorType(GLenum type)
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000207{
208 switch (type)
209 {
Jamie Madill493f9572018-05-24 19:52:15 -0400210 case GL_FLOAT:
211 case GL_INT:
212 case GL_UNSIGNED_INT:
213 return GL_BOOL;
214 case GL_FLOAT_VEC2:
215 case GL_INT_VEC2:
216 case GL_UNSIGNED_INT_VEC2:
217 return GL_BOOL_VEC2;
218 case GL_FLOAT_VEC3:
219 case GL_INT_VEC3:
220 case GL_UNSIGNED_INT_VEC3:
221 return GL_BOOL_VEC3;
222 case GL_FLOAT_VEC4:
223 case GL_INT_VEC4:
224 case GL_UNSIGNED_INT_VEC4:
225 return GL_BOOL_VEC4;
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000226
Jamie Madill493f9572018-05-24 19:52:15 -0400227 default:
228 UNREACHABLE();
229 return GL_NONE;
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000230 }
231}
232
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000233int VariableRowCount(GLenum type)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000234{
235 switch (type)
236 {
Jamie Madill493f9572018-05-24 19:52:15 -0400237 case GL_NONE:
238 return 0;
239 case GL_BOOL:
240 case GL_FLOAT:
241 case GL_INT:
242 case GL_UNSIGNED_INT:
243 case GL_BOOL_VEC2:
244 case GL_FLOAT_VEC2:
245 case GL_INT_VEC2:
246 case GL_UNSIGNED_INT_VEC2:
247 case GL_BOOL_VEC3:
248 case GL_FLOAT_VEC3:
249 case GL_INT_VEC3:
250 case GL_UNSIGNED_INT_VEC3:
251 case GL_BOOL_VEC4:
252 case GL_FLOAT_VEC4:
253 case GL_INT_VEC4:
254 case GL_UNSIGNED_INT_VEC4:
255 case GL_SAMPLER_2D:
256 case GL_SAMPLER_3D:
257 case GL_SAMPLER_CUBE:
258 case GL_SAMPLER_2D_ARRAY:
259 case GL_SAMPLER_EXTERNAL_OES:
260 case GL_SAMPLER_2D_RECT_ANGLE:
261 case GL_SAMPLER_2D_MULTISAMPLE:
262 case GL_INT_SAMPLER_2D:
263 case GL_INT_SAMPLER_3D:
264 case GL_INT_SAMPLER_CUBE:
265 case GL_INT_SAMPLER_2D_ARRAY:
266 case GL_INT_SAMPLER_2D_MULTISAMPLE:
267 case GL_UNSIGNED_INT_SAMPLER_2D:
268 case GL_UNSIGNED_INT_SAMPLER_3D:
269 case GL_UNSIGNED_INT_SAMPLER_CUBE:
270 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
271 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
272 case GL_SAMPLER_2D_SHADOW:
273 case GL_SAMPLER_CUBE_SHADOW:
274 case GL_SAMPLER_2D_ARRAY_SHADOW:
275 case GL_IMAGE_2D:
276 case GL_INT_IMAGE_2D:
277 case GL_UNSIGNED_INT_IMAGE_2D:
278 case GL_IMAGE_2D_ARRAY:
279 case GL_INT_IMAGE_2D_ARRAY:
280 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
281 case GL_IMAGE_3D:
282 case GL_INT_IMAGE_3D:
283 case GL_UNSIGNED_INT_IMAGE_3D:
284 case GL_IMAGE_CUBE:
285 case GL_INT_IMAGE_CUBE:
286 case GL_UNSIGNED_INT_IMAGE_CUBE:
287 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
288 return 1;
289 case GL_FLOAT_MAT2:
290 case GL_FLOAT_MAT3x2:
291 case GL_FLOAT_MAT4x2:
292 return 2;
293 case GL_FLOAT_MAT3:
294 case GL_FLOAT_MAT2x3:
295 case GL_FLOAT_MAT4x3:
296 return 3;
297 case GL_FLOAT_MAT4:
298 case GL_FLOAT_MAT2x4:
299 case GL_FLOAT_MAT3x4:
300 return 4;
301 default:
302 UNREACHABLE();
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000303 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000304
305 return 0;
306}
307
308int VariableColumnCount(GLenum type)
309{
310 switch (type)
311 {
Jamie Madill493f9572018-05-24 19:52:15 -0400312 case GL_NONE:
313 return 0;
314 case GL_BOOL:
315 case GL_FLOAT:
316 case GL_INT:
317 case GL_UNSIGNED_INT:
318 case GL_SAMPLER_2D:
319 case GL_SAMPLER_3D:
320 case GL_SAMPLER_CUBE:
321 case GL_SAMPLER_2D_ARRAY:
322 case GL_SAMPLER_2D_MULTISAMPLE:
323 case GL_INT_SAMPLER_2D:
324 case GL_INT_SAMPLER_3D:
325 case GL_INT_SAMPLER_CUBE:
326 case GL_INT_SAMPLER_2D_ARRAY:
327 case GL_INT_SAMPLER_2D_MULTISAMPLE:
328 case GL_SAMPLER_EXTERNAL_OES:
329 case GL_SAMPLER_2D_RECT_ANGLE:
330 case GL_UNSIGNED_INT_SAMPLER_2D:
331 case GL_UNSIGNED_INT_SAMPLER_3D:
332 case GL_UNSIGNED_INT_SAMPLER_CUBE:
333 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
334 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
335 case GL_SAMPLER_2D_SHADOW:
336 case GL_SAMPLER_CUBE_SHADOW:
337 case GL_SAMPLER_2D_ARRAY_SHADOW:
338 case GL_IMAGE_2D:
339 case GL_INT_IMAGE_2D:
340 case GL_UNSIGNED_INT_IMAGE_2D:
341 case GL_IMAGE_3D:
342 case GL_INT_IMAGE_3D:
343 case GL_UNSIGNED_INT_IMAGE_3D:
344 case GL_IMAGE_2D_ARRAY:
345 case GL_INT_IMAGE_2D_ARRAY:
346 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
347 case GL_IMAGE_CUBE:
348 case GL_INT_IMAGE_CUBE:
349 case GL_UNSIGNED_INT_IMAGE_CUBE:
350 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
351 return 1;
352 case GL_BOOL_VEC2:
353 case GL_FLOAT_VEC2:
354 case GL_INT_VEC2:
355 case GL_UNSIGNED_INT_VEC2:
356 case GL_FLOAT_MAT2:
357 case GL_FLOAT_MAT2x3:
358 case GL_FLOAT_MAT2x4:
359 return 2;
360 case GL_BOOL_VEC3:
361 case GL_FLOAT_VEC3:
362 case GL_INT_VEC3:
363 case GL_UNSIGNED_INT_VEC3:
364 case GL_FLOAT_MAT3:
365 case GL_FLOAT_MAT3x2:
366 case GL_FLOAT_MAT3x4:
367 return 3;
368 case GL_BOOL_VEC4:
369 case GL_FLOAT_VEC4:
370 case GL_INT_VEC4:
371 case GL_UNSIGNED_INT_VEC4:
372 case GL_FLOAT_MAT4:
373 case GL_FLOAT_MAT4x2:
374 case GL_FLOAT_MAT4x3:
375 return 4;
376 default:
377 UNREACHABLE();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000378 }
379
380 return 0;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000381}
382
Geoff Lang2ec386b2014-12-03 14:44:38 -0500383bool IsSamplerType(GLenum type)
Nicolas Capense6050882013-07-08 10:43:10 -0400384{
385 switch (type)
386 {
Jamie Madill493f9572018-05-24 19:52:15 -0400387 case GL_SAMPLER_2D:
388 case GL_SAMPLER_3D:
389 case GL_SAMPLER_CUBE:
390 case GL_SAMPLER_2D_ARRAY:
391 case GL_SAMPLER_EXTERNAL_OES:
392 case GL_SAMPLER_2D_MULTISAMPLE:
393 case GL_SAMPLER_2D_RECT_ANGLE:
394 case GL_INT_SAMPLER_2D:
395 case GL_INT_SAMPLER_3D:
396 case GL_INT_SAMPLER_CUBE:
397 case GL_INT_SAMPLER_2D_ARRAY:
398 case GL_INT_SAMPLER_2D_MULTISAMPLE:
399 case GL_UNSIGNED_INT_SAMPLER_2D:
400 case GL_UNSIGNED_INT_SAMPLER_3D:
401 case GL_UNSIGNED_INT_SAMPLER_CUBE:
402 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
403 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
404 case GL_SAMPLER_2D_SHADOW:
405 case GL_SAMPLER_CUBE_SHADOW:
406 case GL_SAMPLER_2D_ARRAY_SHADOW:
407 return true;
Nicolas Capense6050882013-07-08 10:43:10 -0400408 }
409
410 return false;
411}
412
Olli Etuahoceb10482017-02-13 12:31:03 +0000413bool IsImageType(GLenum type)
414{
415 switch (type)
416 {
417 case GL_IMAGE_2D:
418 case GL_INT_IMAGE_2D:
419 case GL_UNSIGNED_INT_IMAGE_2D:
420 case GL_IMAGE_3D:
421 case GL_INT_IMAGE_3D:
422 case GL_UNSIGNED_INT_IMAGE_3D:
423 case GL_IMAGE_2D_ARRAY:
424 case GL_INT_IMAGE_2D_ARRAY:
425 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
426 case GL_IMAGE_CUBE:
427 case GL_INT_IMAGE_CUBE:
428 case GL_UNSIGNED_INT_IMAGE_CUBE:
429 return true;
430 }
431 return false;
432}
433
jchen104cdac9e2017-05-08 11:01:20 +0800434bool IsAtomicCounterType(GLenum type)
435{
436 return type == GL_UNSIGNED_INT_ATOMIC_COUNTER;
437}
438
Olli Etuahoceb10482017-02-13 12:31:03 +0000439bool IsOpaqueType(GLenum type)
440{
441 // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
jchen104cdac9e2017-05-08 11:01:20 +0800442 return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
Olli Etuahoceb10482017-02-13 12:31:03 +0000443}
444
shannon.woods%transgaming.com@gtempaccount.com02e11f32013-04-13 03:40:50 +0000445bool IsMatrixType(GLenum type)
446{
447 return VariableRowCount(type) > 1;
448}
449
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000450GLenum TransposeMatrixType(GLenum type)
451{
452 if (!IsMatrixType(type))
453 {
454 return type;
455 }
456
457 switch (type)
458 {
Jamie Madill493f9572018-05-24 19:52:15 -0400459 case GL_FLOAT_MAT2:
460 return GL_FLOAT_MAT2;
461 case GL_FLOAT_MAT3:
462 return GL_FLOAT_MAT3;
463 case GL_FLOAT_MAT4:
464 return GL_FLOAT_MAT4;
465 case GL_FLOAT_MAT2x3:
466 return GL_FLOAT_MAT3x2;
467 case GL_FLOAT_MAT3x2:
468 return GL_FLOAT_MAT2x3;
469 case GL_FLOAT_MAT2x4:
470 return GL_FLOAT_MAT4x2;
471 case GL_FLOAT_MAT4x2:
472 return GL_FLOAT_MAT2x4;
473 case GL_FLOAT_MAT3x4:
474 return GL_FLOAT_MAT4x3;
475 case GL_FLOAT_MAT4x3:
476 return GL_FLOAT_MAT3x4;
477 default:
478 UNREACHABLE();
479 return GL_NONE;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000480 }
481}
482
Jamie Madill8c6befc2013-06-20 11:55:55 -0400483int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix)
484{
485 ASSERT(IsMatrixType(type));
486 return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type);
487}
488
489int MatrixComponentCount(GLenum type, bool isRowMajorMatrix)
490{
491 ASSERT(IsMatrixType(type));
492 return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type);
493}
494
Jamie Madillf2575982014-06-25 16:04:54 -0400495int VariableRegisterCount(GLenum type)
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +0000496{
497 return IsMatrixType(type) ? VariableColumnCount(type) : 1;
498}
499
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000500int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize)
501{
502 ASSERT(allocationSize <= bitsSize);
503
Jamie Madill493f9572018-05-24 19:52:15 -0400504 unsigned int mask = std::numeric_limits<unsigned int>::max() >>
505 (std::numeric_limits<unsigned int>::digits - allocationSize);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +0000506
507 for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++)
508 {
509 if ((*bits & mask) == 0)
510 {
511 *bits |= mask;
512 return i;
513 }
514
515 mask <<= 1;
516 }
517
518 return -1;
519}
520
Geoff Lang3edfe032015-09-04 16:38:24 -0400521IndexRange ComputeIndexRange(GLenum indexType,
522 const GLvoid *indices,
523 size_t count,
524 bool primitiveRestartEnabled)
Geoff Lang831b1952015-05-05 11:02:27 -0400525{
526 switch (indexType)
527 {
Geoff Lang3edfe032015-09-04 16:38:24 -0400528 case GL_UNSIGNED_BYTE:
529 return ComputeTypedIndexRange(static_cast<const GLubyte *>(indices), count,
530 primitiveRestartEnabled,
531 GetPrimitiveRestartIndex(indexType));
532 case GL_UNSIGNED_SHORT:
533 return ComputeTypedIndexRange(static_cast<const GLushort *>(indices), count,
534 primitiveRestartEnabled,
535 GetPrimitiveRestartIndex(indexType));
536 case GL_UNSIGNED_INT:
537 return ComputeTypedIndexRange(static_cast<const GLuint *>(indices), count,
538 primitiveRestartEnabled,
539 GetPrimitiveRestartIndex(indexType));
540 default:
541 UNREACHABLE();
542 return IndexRange();
543 }
544}
545
546GLuint GetPrimitiveRestartIndex(GLenum indexType)
547{
548 switch (indexType)
549 {
550 case GL_UNSIGNED_BYTE:
551 return 0xFF;
552 case GL_UNSIGNED_SHORT:
553 return 0xFFFF;
554 case GL_UNSIGNED_INT:
555 return 0xFFFFFFFF;
556 default:
557 UNREACHABLE();
558 return 0;
Geoff Lang831b1952015-05-05 11:02:27 -0400559 }
560}
561
Jamie Madill493f9572018-05-24 19:52:15 -0400562bool IsTriangleMode(PrimitiveMode drawMode)
daniel@transgaming.com97c852b2012-12-20 20:56:23 +0000563{
564 switch (drawMode)
565 {
Jamie Madill493f9572018-05-24 19:52:15 -0400566 case PrimitiveMode::Triangles:
567 case PrimitiveMode::TriangleFan:
568 case PrimitiveMode::TriangleStrip:
569 return true;
570 case PrimitiveMode::Points:
571 case PrimitiveMode::Lines:
572 case PrimitiveMode::LineLoop:
573 case PrimitiveMode::LineStrip:
574 return false;
575 default:
576 UNREACHABLE();
daniel@transgaming.com97c852b2012-12-20 20:56:23 +0000577 }
578
579 return false;
580}
581
Geoff Lang4f0e0032017-05-01 16:04:35 -0400582bool IsIntegerFormat(GLenum unsizedFormat)
583{
584 switch (unsizedFormat)
585 {
586 case GL_RGBA_INTEGER:
587 case GL_RGB_INTEGER:
588 case GL_RG_INTEGER:
589 case GL_RED_INTEGER:
590 return true;
591
592 default:
593 return false;
594 }
595}
596
Jamie Madill865d1452014-07-02 15:31:20 -0400597// [OpenGL ES SL 3.00.4] Section 11 p. 120
598// Vertex Outs/Fragment Ins packing priorities
599int VariableSortOrder(GLenum type)
600{
601 switch (type)
602 {
Jamie Madill493f9572018-05-24 19:52:15 -0400603 // 1. Arrays of mat4 and mat4
604 // Non-square matrices of type matCxR consume the same space as a square
605 // matrix of type matN where N is the greater of C and R
606 case GL_FLOAT_MAT4:
607 case GL_FLOAT_MAT2x4:
608 case GL_FLOAT_MAT3x4:
609 case GL_FLOAT_MAT4x2:
610 case GL_FLOAT_MAT4x3:
611 return 0;
Jamie Madill865d1452014-07-02 15:31:20 -0400612
Jamie Madill493f9572018-05-24 19:52:15 -0400613 // 2. Arrays of mat2 and mat2 (since they occupy full rows)
614 case GL_FLOAT_MAT2:
615 return 1;
Jamie Madill865d1452014-07-02 15:31:20 -0400616
Jamie Madill493f9572018-05-24 19:52:15 -0400617 // 3. Arrays of vec4 and vec4
618 case GL_FLOAT_VEC4:
619 case GL_INT_VEC4:
620 case GL_BOOL_VEC4:
621 case GL_UNSIGNED_INT_VEC4:
622 return 2;
Jamie Madill865d1452014-07-02 15:31:20 -0400623
Jamie Madill493f9572018-05-24 19:52:15 -0400624 // 4. Arrays of mat3 and mat3
625 case GL_FLOAT_MAT3:
626 case GL_FLOAT_MAT2x3:
627 case GL_FLOAT_MAT3x2:
628 return 3;
Jamie Madill865d1452014-07-02 15:31:20 -0400629
Jamie Madill493f9572018-05-24 19:52:15 -0400630 // 5. Arrays of vec3 and vec3
631 case GL_FLOAT_VEC3:
632 case GL_INT_VEC3:
633 case GL_BOOL_VEC3:
634 case GL_UNSIGNED_INT_VEC3:
635 return 4;
Jamie Madill865d1452014-07-02 15:31:20 -0400636
Jamie Madill493f9572018-05-24 19:52:15 -0400637 // 6. Arrays of vec2 and vec2
638 case GL_FLOAT_VEC2:
639 case GL_INT_VEC2:
640 case GL_BOOL_VEC2:
641 case GL_UNSIGNED_INT_VEC2:
642 return 5;
Jamie Madill865d1452014-07-02 15:31:20 -0400643
Jamie Madill493f9572018-05-24 19:52:15 -0400644 // 7. Single component types
645 case GL_FLOAT:
646 case GL_INT:
647 case GL_BOOL:
648 case GL_UNSIGNED_INT:
649 case GL_SAMPLER_2D:
650 case GL_SAMPLER_CUBE:
651 case GL_SAMPLER_EXTERNAL_OES:
652 case GL_SAMPLER_2D_RECT_ANGLE:
653 case GL_SAMPLER_2D_ARRAY:
654 case GL_SAMPLER_2D_MULTISAMPLE:
655 case GL_SAMPLER_3D:
656 case GL_INT_SAMPLER_2D:
657 case GL_INT_SAMPLER_3D:
658 case GL_INT_SAMPLER_CUBE:
659 case GL_INT_SAMPLER_2D_ARRAY:
660 case GL_INT_SAMPLER_2D_MULTISAMPLE:
661 case GL_UNSIGNED_INT_SAMPLER_2D:
662 case GL_UNSIGNED_INT_SAMPLER_3D:
663 case GL_UNSIGNED_INT_SAMPLER_CUBE:
664 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
665 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
666 case GL_SAMPLER_2D_SHADOW:
667 case GL_SAMPLER_2D_ARRAY_SHADOW:
668 case GL_SAMPLER_CUBE_SHADOW:
669 case GL_IMAGE_2D:
670 case GL_INT_IMAGE_2D:
671 case GL_UNSIGNED_INT_IMAGE_2D:
672 case GL_IMAGE_3D:
673 case GL_INT_IMAGE_3D:
674 case GL_UNSIGNED_INT_IMAGE_3D:
675 case GL_IMAGE_2D_ARRAY:
676 case GL_INT_IMAGE_2D_ARRAY:
677 case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
678 case GL_IMAGE_CUBE:
679 case GL_INT_IMAGE_CUBE:
680 case GL_UNSIGNED_INT_IMAGE_CUBE:
681 case GL_UNSIGNED_INT_ATOMIC_COUNTER:
682 return 6;
Jamie Madill865d1452014-07-02 15:31:20 -0400683
Jamie Madill493f9572018-05-24 19:52:15 -0400684 default:
685 UNREACHABLE();
686 return 0;
Jamie Madill865d1452014-07-02 15:31:20 -0400687 }
688}
689
Olli Etuahoc8538042017-09-27 11:20:15 +0300690std::string ParseResourceName(const std::string &name, std::vector<unsigned int> *outSubscripts)
Geoff Langcfaeaa92015-04-14 13:41:02 -0400691{
Olli Etuahoc8538042017-09-27 11:20:15 +0300692 if (outSubscripts)
Geoff Langcfaeaa92015-04-14 13:41:02 -0400693 {
Olli Etuahoc8538042017-09-27 11:20:15 +0300694 outSubscripts->clear();
Geoff Langcfaeaa92015-04-14 13:41:02 -0400695 }
Olli Etuahoc8538042017-09-27 11:20:15 +0300696 // Strip any trailing array indexing operators and retrieve the subscripts.
697 size_t baseNameLength = name.length();
698 bool hasIndex = true;
699 while (hasIndex)
Geoff Langcfaeaa92015-04-14 13:41:02 -0400700 {
Olli Etuahoc8538042017-09-27 11:20:15 +0300701 size_t open = name.find_last_of('[', baseNameLength - 1);
702 size_t close = name.find_last_of(']', baseNameLength - 1);
703 hasIndex = (open != std::string::npos) && (close == baseNameLength - 1);
704 if (hasIndex)
Geoff Langcfaeaa92015-04-14 13:41:02 -0400705 {
Olli Etuahoc8538042017-09-27 11:20:15 +0300706 baseNameLength = open;
707 if (outSubscripts)
708 {
709 int index = atoi(name.substr(open + 1).c_str());
710 if (index >= 0)
711 {
712 outSubscripts->push_back(index);
713 }
714 else
715 {
716 outSubscripts->push_back(GL_INVALID_INDEX);
717 }
718 }
Geoff Langcfaeaa92015-04-14 13:41:02 -0400719 }
720 }
721
Olli Etuahoc8538042017-09-27 11:20:15 +0300722 return name.substr(0, baseNameLength);
Geoff Langcfaeaa92015-04-14 13:41:02 -0400723}
724
jchen108225e732017-11-14 16:29:03 +0800725const sh::ShaderVariable *FindShaderVarField(const sh::ShaderVariable &var,
726 const std::string &fullName)
727{
728 if (var.fields.empty())
729 {
730 return nullptr;
731 }
732 size_t pos = fullName.find_first_of(".");
733 if (pos == std::string::npos)
734 {
735 return nullptr;
736 }
737 std::string topName = fullName.substr(0, pos);
738 if (topName != var.name)
739 {
740 return nullptr;
741 }
742 std::string fieldName = fullName.substr(pos + 1);
743 if (fieldName.empty())
744 {
745 return nullptr;
746 }
747 for (const auto &field : var.fields)
748 {
749 if (field.name == fieldName)
750 {
751 return &field;
752 }
753 }
754 return nullptr;
755}
756
Olli Etuaho465835d2017-09-26 13:34:10 +0300757unsigned int ArraySizeProduct(const std::vector<unsigned int> &arraySizes)
758{
759 unsigned int arraySizeProduct = 1u;
760 for (unsigned int arraySize : arraySizes)
761 {
762 arraySizeProduct *= arraySize;
763 }
764 return arraySizeProduct;
765}
766
Olli Etuahod2551232017-10-26 20:03:33 +0300767unsigned int ParseArrayIndex(const std::string &name, size_t *nameLengthWithoutArrayIndexOut)
Jamie Madill4a3c2342015-10-08 12:58:45 -0400768{
Olli Etuahod2551232017-10-26 20:03:33 +0300769 ASSERT(nameLengthWithoutArrayIndexOut != nullptr);
Jamie Madill4a3c2342015-10-08 12:58:45 -0400770
771 // Strip any trailing array operator and retrieve the subscript
Olli Etuahod2551232017-10-26 20:03:33 +0300772 size_t open = name.find_last_of('[');
773 if (open != std::string::npos && name.back() == ']')
Jamie Madill4a3c2342015-10-08 12:58:45 -0400774 {
Olli Etuahod2551232017-10-26 20:03:33 +0300775 bool indexIsValidDecimalNumber = true;
776 for (size_t i = open + 1; i < name.length() - 1u; ++i)
777 {
778 if (!isdigit(name[i]))
779 {
780 indexIsValidDecimalNumber = false;
781 break;
782 }
783 }
784 if (indexIsValidDecimalNumber)
785 {
Bryan Bernhart (Intel Americas Inc)f4f293e2017-11-06 15:56:29 -0800786 errno = 0; // reset global error flag.
787 unsigned long subscript =
788 strtoul(name.c_str() + open + 1, /*endptr*/ nullptr, /*radix*/ 10);
789
790 // Check if resulting integer is out-of-range or conversion error.
791 if ((subscript <= static_cast<unsigned long>(UINT_MAX)) &&
792 !(subscript == ULONG_MAX && errno == ERANGE) && !(errno != 0 && subscript == 0))
793 {
794 *nameLengthWithoutArrayIndexOut = open;
795 return static_cast<unsigned int>(subscript);
796 }
Olli Etuahod2551232017-10-26 20:03:33 +0300797 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400798 }
799
Olli Etuahod2551232017-10-26 20:03:33 +0300800 *nameLengthWithoutArrayIndexOut = name.length();
Bryan Bernhart (Intel Americas Inc)f4f293e2017-11-06 15:56:29 -0800801 return GL_INVALID_INDEX;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000802}
803
Geoff Langee6884e2017-11-09 16:51:11 -0500804const char *GetGenericErrorMessage(GLenum error)
805{
806 switch (error)
807 {
808 case GL_NO_ERROR:
809 return "";
810 case GL_INVALID_ENUM:
811 return "Invalid enum.";
812 case GL_INVALID_VALUE:
813 return "Invalid value.";
814 case GL_INVALID_OPERATION:
815 return "Invalid operation.";
816 case GL_STACK_OVERFLOW:
817 return "Stack overflow.";
818 case GL_STACK_UNDERFLOW:
819 return "Stack underflow.";
820 case GL_OUT_OF_MEMORY:
821 return "Out of memory.";
822 case GL_INVALID_FRAMEBUFFER_OPERATION:
823 return "Invalid framebuffer operation.";
824 default:
825 UNREACHABLE();
826 return "Unknown error.";
827 }
828}
829
Jamie Madill8957b6c2017-11-14 12:40:38 -0500830unsigned int ElementTypeSize(GLenum elementType)
831{
832 switch (elementType)
833 {
834 case GL_UNSIGNED_BYTE:
835 return sizeof(GLubyte);
836 case GL_UNSIGNED_SHORT:
837 return sizeof(GLushort);
838 case GL_UNSIGNED_INT:
839 return sizeof(GLuint);
840 default:
841 UNREACHABLE();
842 return 0;
843 }
844}
845
Jamie Madill4a3c2342015-10-08 12:58:45 -0400846} // namespace gl
847
Geoff Langa8406172015-07-21 16:53:39 -0400848namespace egl
849{
850static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 1,
851 "Unexpected EGL cube map enum value.");
852static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 2,
853 "Unexpected EGL cube map enum value.");
854static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 3,
855 "Unexpected EGL cube map enum value.");
856static_assert(EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 4,
857 "Unexpected EGL cube map enum value.");
858static_assert(EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR == 5,
859 "Unexpected EGL cube map enum value.");
860
861bool IsCubeMapTextureTarget(EGLenum target)
862{
863 return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
864}
865
866size_t CubeMapTextureTargetToLayerIndex(EGLenum target)
867{
868 ASSERT(IsCubeMapTextureTarget(target));
869 return target - static_cast<size_t>(FirstCubeMapTextureTarget);
870}
871
872EGLenum LayerIndexToCubeMapTextureTarget(size_t index)
873{
874 ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
875 return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
876}
877
878bool IsTextureTarget(EGLenum target)
879{
880 switch (target)
881 {
882 case EGL_GL_TEXTURE_2D_KHR:
883 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
884 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
885 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
886 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
887 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
888 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
889 case EGL_GL_TEXTURE_3D_KHR:
890 return true;
891
892 default:
893 return false;
894 }
895}
896
897bool IsRenderbufferTarget(EGLenum target)
898{
899 return target == EGL_GL_RENDERBUFFER_KHR;
900}
Geoff Langee6884e2017-11-09 16:51:11 -0500901
902const char *GetGenericErrorMessage(EGLint error)
903{
904 switch (error)
905 {
906 case EGL_SUCCESS:
907 return "";
908 case EGL_NOT_INITIALIZED:
909 return "Not initialized.";
910 case EGL_BAD_ACCESS:
911 return "Bad access.";
912 case EGL_BAD_ALLOC:
913 return "Bad allocation.";
914 case EGL_BAD_ATTRIBUTE:
915 return "Bad attribute.";
916 case EGL_BAD_CONFIG:
917 return "Bad config.";
918 case EGL_BAD_CONTEXT:
919 return "Bad context.";
920 case EGL_BAD_CURRENT_SURFACE:
921 return "Bad current surface.";
922 case EGL_BAD_DISPLAY:
923 return "Bad display.";
924 case EGL_BAD_MATCH:
925 return "Bad match.";
926 case EGL_BAD_NATIVE_WINDOW:
927 return "Bad native window.";
928 case EGL_BAD_PARAMETER:
929 return "Bad parameter.";
930 case EGL_BAD_SURFACE:
931 return "Bad surface.";
932 case EGL_CONTEXT_LOST:
933 return "Context lost.";
934 case EGL_BAD_STREAM_KHR:
935 return "Bad stream.";
936 case EGL_BAD_STATE_KHR:
937 return "Bad state.";
938 case EGL_BAD_DEVICE_EXT:
939 return "Bad device.";
940 default:
941 UNREACHABLE();
942 return "Unknown error.";
943 }
944}
945
Jamie Madill8b9b7922016-05-19 13:13:37 -0400946} // namespace egl
Geoff Langa8406172015-07-21 16:53:39 -0400947
948namespace egl_gl
949{
Geoff Langa8406172015-07-21 16:53:39 -0400950GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
951{
952 return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
953}
Jamie Madill8b9b7922016-05-19 13:13:37 -0400954} // namespace egl_gl
Geoff Langa8406172015-07-21 16:53:39 -0400955
Geoff Langc5a2a172017-01-13 15:55:07 -0500956namespace gl_egl
957{
958EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType)
959{
960 switch (glComponentType)
961 {
962 case GL_FLOAT:
963 return EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
964
965 case GL_UNSIGNED_NORMALIZED:
966 return EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
967
968 default:
969 UNREACHABLE();
970 return EGL_NONE;
971 }
972}
973} // namespace gl_egl
974
Austin Kinross922a9fb2014-10-21 14:26:33 -0700975#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000976std::string getTempPath()
977{
Shannon Woodsfb839472014-06-16 13:21:41 -0400978#ifdef ANGLE_PLATFORM_WINDOWS
Austin Kinross922a9fb2014-10-21 14:26:33 -0700979 char path[MAX_PATH];
980 DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path);
981 if (pathLen == 0)
982 {
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000983 UNREACHABLE();
984 return std::string();
Austin Kinross922a9fb2014-10-21 14:26:33 -0700985 }
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +0000986
Austin Kinross922a9fb2014-10-21 14:26:33 -0700987 UINT unique = GetTempFileNameA(path, "sh", 0, path);
988 if (unique == 0)
989 {
990 UNREACHABLE();
991 return std::string();
992 }
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +0000993
Austin Kinross922a9fb2014-10-21 14:26:33 -0700994 return path;
Geoff Lang83217792014-01-16 09:52:38 -0500995#else
996 UNIMPLEMENTED();
997 return "";
998#endif
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000999}
1000
Jamie Madill493f9572018-05-24 19:52:15 -04001001void writeFile(const char *path, const void *content, size_t size)
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001002{
Jamie Madill493f9572018-05-24 19:52:15 -04001003 FILE *file = fopen(path, "w");
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00001004 if (!file)
1005 {
1006 UNREACHABLE();
1007 return;
1008 }
1009
1010 fwrite(content, sizeof(char), size, file);
1011 fclose(file);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001012}
Jamie Madill493f9572018-05-24 19:52:15 -04001013#endif // !ANGLE_ENABLE_WINDOWS_STORE
Cooper Partin88d3b8c2014-10-08 10:41:56 -07001014
Jamie Madill493f9572018-05-24 19:52:15 -04001015#if defined(ANGLE_PLATFORM_WINDOWS)
Cooper Partin88d3b8c2014-10-08 10:41:56 -07001016
Cooper Partin1edac3b2014-11-20 13:49:27 -08001017// Causes the thread to relinquish the remainder of its time slice to any
1018// other thread that is ready to run.If there are no other threads ready
1019// to run, the function returns immediately, and the thread continues execution.
1020void ScheduleYield()
Cooper Partin88d3b8c2014-10-08 10:41:56 -07001021{
Geoff Lange5f735f2015-09-17 13:26:59 -04001022 Sleep(0);
Cooper Partin88d3b8c2014-10-08 10:41:56 -07001023}
1024
Kenneth Russellb23deb22014-11-21 14:53:56 -08001025#endif